I'm pretty new to react native and async programming, and trying to understand how to "sync" redux state values and local state values.
For example, I have a text field "aboutMe" stored server side, and using mapStateToProps to place it into props:
const mapStateToProps = (state) => {
return { aboutMe: state.aboutMe };
}
In render, I have a TextInput I'm using so that the user can edit this field, and I would like to default to what is saved on the server side:
<TextInput
onChangeText={(aboutMe) => {
this.setState({aboutMe});
}}
value={this.state.aboutMe}
/>
Basically, somewhere I need to call
this.setState({ aboutMe: this.props.aboutMe });
Where is the right place to this? I was trying to use componentWillReceiveProps, but that lifecycle method is not called on constructor, so I would need to setState twice (in constructor and in componentWillReceiveProps).
Is there another way to do this? I feel like this is a pretty generic problem that a lot of react native developers have solved but I couldn't find a generally accepted way online.
Thanks!
Edit:
I have alot of TextInputs, so I have a separate button to call the action to save the variables:
<Button onPress={()=>{
this.props.saveUserInput(this.state.aboutMe,
this.state.name, this.state.address, ....}}>
<Text> Save changes </Text>
</Button>
From the comments, I understand that it's possible to call the save action onChangeText... but is that too much traffic back and forth? Would it be better to save all of the variables locally to state and then call a save for everything at once? Also, what if the user would like to "cancel" instead of save? The changes would have been already saved and we will not be able to discard changes?
1) If your component is a controlled component (you need state in it) and the request is asynchronous indeed you have to set the state in the componentWillReceiveProps
like this:
class ExampleComp extends Component {
constructor(props) {
super(props);
this.state = {
aboutMe: ""
}
}
componentWillReceiveProps(nextProps) {
this.setState({
aboutMe: nextProps.aboutMe,
});
}
render() {
return (
<TextInput
onChangeText={(aboutMe) => {
this.setState({aboutMe});
}}
value={this.state.aboutMe}
/>
);
}
}
Keep in mind the key here is that the state must remain the single source of truth from now on.
2) The other option would be, you can wait until the request is finished in the parent component and then set the aboutMe
in your constructor, this way you can avoid componentWillReceiveProps
. For example:
class ParentComp extends Component {
render() {
return (
<div>
{this.props.aboutMe && <ExampleComp/>}
</div>
);
}
}
class ExampleComp extends Component {
constructor(props) {
super(props);
this.state = {
aboutMe: props.aboutMe
}
}
render() {
return (
<TextInput
onChangeText={(aboutMe) => {
this.setState({aboutMe});
}}
value={this.state.aboutMe}
/>
);
}
}
The downside of this is that the text input won't be shown until the request is finished.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With