I was trying to use react-py to use pyodide in my NextJs app. It requires it wrap the component where python is to be used with `PythonProvider`. I have used the PythonProvider and usePython in the same page (client side) but the sendInput stopped working.
After some debugging I figured out that the input related values in the PythonProvider was changing but it was not updated in usePython hook (wrapper of PythonContext). But surprisingly if I move the Provider to layout.js it starts working fine.
Is there any restriction in place that ContextProvider and useContext mustn’t be used in the same page?
Not Updating Page.js
'use client'
import { useState,useEffect } from 'react'
import { PythonProvider, usePython } from '../../react-py/src'
const Page = () => {
const [code, setCode] = useState('input("hello:")')
const {interruptExecution,isAwaitingInput,isLoading,isReady,isRunning,prompt,runPython,sendInput,stderr,stdout}=usePython()
useEffect(() => {
navigator.serviceWorker
.register('/service-worker.js')
.then((registration) =>
console.log(
'Service Worker registration successful with scope: ',
registration.scope
)
)
.catch((err) => console.log('Service Worker registration failed: ', err))
}, [])
return (
<PythonProvider>
{isAwaitingInput && <p>INPUT A</p>}
{isLoading && <p>Loading A</p>}
{isReady && <p>READY A</p>}
{isRunning && <p>RUNNING A</p>}
<input type="text" value={code} onChange={e=>setCode(e.target.value)}/>
<button onClick={e=>{runPython(code)}}>RUN</button>
<button onClick={e=>{sendInput('sdfghj')}}>SEND INPUT</button>
<button onClick={e=>{interruptExecution()}}>INTERUPT</button>
<p>{stdout}</p>
</PythonProvider>
)
}
export default Page
Though this works->
layout.j
s
'use client'
import { Inter } from "next/font/google";
import "./globals.css";
import { useEffect } from "react";
import { PythonProvider } from "../../react-py/src";
const inter = Inter({ subsets: ["latin"] });
export default function RootLayout({ children }) {
useEffect(() => {
navigator.serviceWorker
.register('/service-worker.js')
.then((registration) =>
console.log(
'Service Worker registration successful with scope: ',
registration.scope
)
)
.catch((err) => console.log('Service Worker registration failed: ', err))
}, [])
return (
<html lang="en">
<PythonProvider>
<body className={inter.className}>{children}</body>
</PythonProvider>
</html>
);
}
`page.js`
'use client'
import { useState,useEffect } from 'react'
import { PythonProvider, usePython } from '../../react-py/src'
const Page = () => {
const [code, setCode] = useState('input("hello:")')
const {interruptExecution,isAwaitingInput,isLoading,isReady,isRunning,prompt,runPython,sendInput,stderr,stdout}=usePython()
return (
<>
{isAwaitingInput && <p>INPUT A</p>}
{isLoading && <p>Loading A</p>}
{isReady && <p>READY A</p>}
{isRunning && <p>RUNNING A</p>}
<input type="text" value={code} onChange={e=>setCode(e.target.value)}/>
<button onClick={e=>{runPython(code)}}>RUN</button>
<button onClick={e=>{sendInput('sdfghj')}}>SEND INPUT</button>
<button onClick={e=>{interruptExecution()}}>INTERUPT</button>
<p>{stdout}</p>
</>
)
}
export default Page
...
2
Answers
without wrapping it with the PythonProvider again.***
PythonProvider is rendered before any component
Creator of
react-py
here.When using the
usePython
hook in your Next.js application, it is crucial to ensure that thePythonProvider
component wraps around any components that rely on this hook. This is because thePythonProvider
supplies the necessary context for theusePython
hook to function properly.