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
...
Creator of react-py
here.
When using the usePython
hook in your Next.js application, it is crucial to ensure that the PythonProvider
component wraps around any components that rely on this hook. This is because the PythonProvider
supplies the necessary context for the usePython
hook to function properly.