Benefits of State?
cgarciae opened this issue · 2 comments
I have this component which uses the constructor to fetch some data, then updates its fields. I've seen the state
property but I don't see how its usefull (I am new to React) since I prefer typed Dart fields. So in this example you'll see that after I set the data, I have to call setState({})
and notice how I pass and empty map just to force React to re-render.
var myComponent = registerComponent(() => new MyComponent());
class MyComponent extends Component
{
List<User> users = [];
MyComponent ()
{
init();
}
init () async
{
await new Future.delayed(new Duration(seconds: 2));
var json = await HttpRequest.getString("users.json");
users = decodeJson(json, User);
//Setting state just to rerender
setState({});
}
List get usersRender => users.map((user) =>
div ({},[
h1 ({}, user.name),
p ({}, user.descripcion)
])
).toList();
@override
render() => div({}, usersRender);
}
Another question is how to access the MyComponent
instance from the outside to (for example) add a user?
@cgarciae react is trying to maintain the invariant, that the render
method is dependent only on props
and state
. This enables powerful things later, especially in combination with immutable data structures and should component update.
I recommend reading more about React from the official sources: https://facebook.github.io/react/index.html
@cgarciae My view how to use state.
First of all if you need to access to field from outside than having it inside of component is not good idea. You shoud have it declared outside and pass it in props.
Secondly on difference of state and local variables. Clear benefit of keeping variables in state is that if you change somehting than redraw is triggered automaticaly. If you keep it in local variable every time you change it you have to triggere redraw. For trigereing redraw you can use setState({})
or you can use helper redraw()
which does exactly same thing.
Another isue with your code is that is't not good idea to trigger init in constructor and you should almost never do work in constructor instead do it in componentWillMount()
Last of all here is another aproach to have somehting in local variables with automatic redraw with data type which is observable(something like DataReference
from clean_data
package see docs or take insipiration and implement your own observable from this code. Then you can make patter like this:
class Login extends Component {
DataReference<String> email = new DataReference('');
DataReference<String> pwd = new DataReference('');;
List<StreamSubscription> ss;
componentWillMount() {
ss = [
email.onChange.listen((_) => redraw()),
pwd .onChange.listen((_) => redraw()),
];
}
componentWillUnmount() {
ss.forEach((s) => s.cancel());
}
onSomeRandomEventCallback() {
email.value = 'Something';
//no need to call redraw
}
render() {
return div({},[
input({'onChange': (e) => email.value = e.target.value}, email.value),
input({'onChange': (e) => pwd.value = e.target.value}, pwd.value),
...
])
}
}
Or you can use local variables as storige for data which will not trigger redraw like ss
in previous example or somehting like last time when i refreshed data, or timers...
Hope this helped.