When Wrapping React, how to specify generated `import` style(Tag) in nextjs?
Describe the bug
Hi Pynecone Team
I am trying to wrap echarts-for-react, a beautiful and fully controlled graphing npm into pynecone app.
In ./.web/pages/index.js, auto generated code is import {ReactECharts} from "echarts-for-react".
To run nextjs, I need import ReactECharts from "echarts-for-react". How to specify that style of import?
And more, if old style var moment = require('moment') is needed, how to specify tag?
Thank you inadvance.
To Reproduce Steps to reproduce the behavior: echarts: https://echarts.apache.org/examples/en/index.html react wrap: https://github.com/hustcc/echarts-for-react
pcconfig.py:
import pynecone as pc
config = pc.Config(
app_name="TEST_Echarts",
db_url="sqlite:///pynecone.db",
env=pc.Env.DEV,
frontend_packages=["echarts","echarts-for-react"],
)
TEST_Echarts.py:
from pcconfig import config
import pynecone as pc
docs_url = "https://pynecone.io/docs/getting-started/introduction"
filename = f"{config.app_name}/{config.app_name}.py"
class ReactECharts(pc.Component):
library = "echarts-for-react"
tag = "ReactECharts"
option: pc.Var[dict]
echarts_react = ReactECharts.create
class State(pc.State):
"""The app state."""
pass
ec_option = {
'xAxis': {
'type': 'category',
'data': ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
'yAxis': {
'type': 'value',
},
'series': [
{
'data': [820, 932, 901, 934, 1290, 1330, 1320],
'type': 'line',
'smooth': True,
},
],
'tooltip': {
'trigger': 'axis',
},
}
def index():
return pc.center(
pc.vstack(
pc.heading("Welcome to Pynecone!", font_size="2em"),
pc.container(
pc.center(pc.text("box here"),),
echarts_react(option=ec_option,),
bg="deepskyblue",
width="100%",
padding=5,
),
spacing="1.5em",
font_size="2em",
),
padding_top="10%",
)
# Add state and page to the app.
app = pc.App(state=State)
app.add_page(index)
app.compile()
./.web/pages/index.js:
import {useEffect, useState} from "react"
import {useRouter} from "next/router"
import {E, updateState} from "/utils/state"
import "focus-visible/dist/focus-visible"
import {Center, Container, Heading, Text, VStack} from "@chakra-ui/react"
import {ReactECharts} from "echarts-for-react"//Error
import NextHead from "next/head"
const EVENT = "http://localhost:8000/event"
export default function Component() {
const [state, setState] = useState({"color": "#db114b", "events": [{"name": "state.hydrate"}]})
const [result, setResult] = useState({"state": null, "events": [], "processing": false})
const router = useRouter()
const Event = events => setState({
...state,
events: [...state.events, ...events],
})
useEffect(() => {
const update = async () => {
if (result.state != null) {
setState({
...result.state,
events: [...state.events, ...result.events],
})
setResult({
state: null,
events: [],
processing: false,
})
}
await updateState(state, result, setResult, EVENT, router)
}
update()
})
return (
<Center sx={{"paddingTop": "10%"}}>
<VStack spacing="1.5em"
sx={{"fontSize": "2em"}}>
<Heading sx={{"fontSize": "2em"}}>
{`Welcome to Pynecone!`}</Heading>
<Container sx={{"bg": "deepskyblue", "width": "100%", "padding": 5}}>
<Center>
<Text>
{`box here`}</Text></Center>
<ReactECharts option={{"xAxis": {"type": "category", "data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]}, "yAxis": {"type": "value"}, "series": [{"data": [820, 932, 901, 934, 1290, 1330, 1320], "type": "line", "smooth": true}], "tooltip": {"trigger": "axis"}}}/></Container></VStack>
<NextHead>
<title>{`Pynecone App`}</title>
<meta content="A Pynecone app."
name="description"/>
<meta property="og:image"
content="favicon.ico"/></NextHead></Center>
)
}
** Specifics (please complete the following information):**
- Python Version: 3.10
- Pynecone Version: 0.1.11
- OS: WSL2
- Browser (Optional):Chrome
Hey, thanks for taking this on!
So to do the default import, you should set the tag to the same (title-case) version of the library.
tag = "EchartsForReact"
Since it's the default import, the name shouldn't matter and it should compile out as <EchartsForReact> tags.
You can also specify additional imports using the _get_imports function, see here for an example.
This all uses the import syntax. If you want to add additional code to be compiled in (like a require statement), you can use the _get_custom_code method and the code returned by that will be included at the top of each page that the component is imported. See here for an example.
Let me know if that works for you!
Hi @picklelo ,
Following your instruction, after TEST_Echarts.py is modified with:
class ReactECharts(pc.Component):
library = "echarts-for-react"
tag = "ReactECharts"
option: pc.Var[dict]
def _get_imports(self):
return {}
def _get_custom_code(self) -> str:
return f'import {self.tag} from "{self.library}"'
./.web/pages/index.js generated import ReactECharts from "echarts-for-react" inplace, and works properly.
Anyhow, how to use get_imports directly to fix above problem?
Ah I see so basically the brackets in your import are the problem. This in interesting because the wrapping react example output doesn't have brackets see here https://pynecone.io/docs/advanced-guide/wrapping-react.
If you need to insert a specific line such as var moment = require('moment') you can do this as so.
Let me know if this helps. Im going to try your branch and see if I can reproduce this
class ReactECharts(pc.Component):
library = "echarts-for-react"
tag = "ReactECharts"
option: pc.Var[dict]
def _get_custom_code(self) -> str:
return f"'var moment = require('moment')"
Ah your right I was able to reproduce this on mine with the brackets. Looking into this.
We also have a discord it may be easier for quick communication for debugging this @picklelo can send invite to this.
Thanks. Could you please invite my dicord: [email protected]
We just added the discord link to the bottom of the README