Closed matejcik closed 6 years ago
Hi @matejcik,
Yes, that is more or less the expected behavior.
No-JSX builders are not React Elements, you have to apply them with no arguments to obtain something you can return in the render method. So, in a component defined as a class, you will have to add the extra ( )
:
export default class App extends React.Component {
render() {
return View(
Text("hello world"),
)()
}
}
That being said, In our experience using this library we found that it's usually more useful to export a No-JSX component builder instead of a real component, since it can be further refined by whoever imports it. This can be done for any functional component, so your code could look like this:
const App = View(
Text("hello world")
)
export default App // We export a component builder instead of a component
But in this particular case, since this is probably your root component and you are not creating it yourself, you might as well export a component like this:
const App = View(
Text("hello world")
)
export default App() // We export a component
I'm closing the ticket now, but let me know if you have any further questions.
thanks for the explanation
is it possible, though, to make stateful components "as builders?"
as in, when I want to use props or state, I need a context where this
is valid and refers to the component, right?
my first attempt was something like:
class App extends React.Component {
constructor(props) {
super(props)
this.state = { value: 0 }
this.render = View(Text("hello ", this.props.name, ", the value is, ", this.state.value))
}
}
which is basically a very wordy way of saying App = View(...)
as you suggest.
but IIUC this freezes the state at call time and it never gets updated (say I add a button that increments the value)
so in the end it seems that I do need a render()
method and the final ()
after the component
or is there some trick I'm missing?
Hm, it turns out that I should read about React.js, because RN docs omit a lot of things. Now I see answers to my original questions which I missed before in the njsx readme.
Also to answer my own question, I expect that there is no "trick" and to get props, I need a function(al component), to get state, i'll need a class-based component. For a simple functional component, I expect I could do some magic with a refinement function (i.e., convert passed "props" to a build-out), but doing an actual function seems like a better choice.
Anyway, thanks for pointing me towards the parts I was missing.
Subclasses of React.Component
always need to have a render method. Using the builder itself as a method for the component will probably not work, since it will only get called without arguments (which will only create a new component with the same state as before).
But in general I would advice to write your stateful component building the rendered subcomponent like this:
class App extends React.Component {
constructor(props) {
super(props)
this.state = { value: 0 }
}
render(){ return View(
Text("hello ", this.props.name, ", the value is, ", this.state.value)
)() // Notice the empty application
}
}
export default App // Now App is a valid component that will re-render on state changes
// You can also create a builder for any component, stateful or not, by calling the njsx function (check https://github.com/uqbar-project/njsx#third-party-component-builders).
export const builder = njsx(App)
So there are two separate concerns here: One is how do you use builders inside a render method for a stateful component and the other is what if you need a builder for said component.
Remember that builders are not components (they just act the same way when you apply them to builders), so your root App will probably need to be exported as a regular React Component.
On a completely separate subject, you might want to check recompose which is a library that allows you to avoid class based components altogether. It's not necessary, but I've been told that is what all cool kids are doing now.
Hope this helps.
trying a React Native hello world with njsx
with this sample component:
the following warning is generated:
the problem is fixed by "calling" the View, as in
return View(....)()
I'm not sure this is the intended usage (i'm quite new to RN), but it seems that returning the component in a
render()
function should be sufficient?