Я новичок в реагировании на собственное и асинхронное программирование и пытаюсь понять, как «синхронизировать» значения состояния редукции и значения локального состояния.
Например, у меня есть текстовое поле aboutMe, которое хранится на стороне сервера, и я использую mapStateToProps для размещения его в props:
const mapStateToProps = (state) => {
return { aboutMe: state.aboutMe };
}
При рендеринге у меня есть TextInput, который я использую, чтобы пользователь мог редактировать это поле, и я хотел бы по умолчанию использовать то, что сохраняется на стороне сервера:
<TextInput
onChangeText = {(aboutMe) => {
this.setState({aboutMe});
}}
value = {this.state.aboutMe}
/>
В принципе, куда-то мне нужно вызвать
this.setState({ aboutMe: this.props.aboutMe });
Где это подходящее место? Я пытался использовать componentWillReceiveProps, но этот метод жизненного цикла не вызывается в конструкторе, поэтому мне нужно было бы setState дважды (в конструкторе и в componentWillReceiveProps).
Есть другой способ сделать это? Мне кажется, что это довольно общая проблема, которую решили многие ответственные нативные разработчики, но я не смог найти общепринятый способ в Интернете.
Спасибо!
Редактировать:
У меня много TextInputs, поэтому у меня есть отдельная кнопка для вызова действия по сохранению переменных:
<Button onPress = {()=>{
this.props.saveUserInput(this.state.aboutMe,
this.state.name, this.state.address, ....}}>
<Text> Save changes </Text>
</Button>
Из комментариев я понимаю, что можно вызвать действие сохранения onChangeText ... но это слишком много трафика туда и обратно? Было бы лучше сохранить все переменные локально в состояние, а затем вызвать сохранение для всего сразу? Кроме того, что, если пользователь хочет «отменить» вместо сохранения? Изменения уже были бы сохранены, и мы не сможем их отменить?
Непонятно, чего вы хотите добиться. Мне кажется, что вы меняете значение с помощью действия, а также с помощью поля ввода. Итак, вам нужно обновить его, когда значение хранилища redux изменяется И когда изменяется поле ввода. Это правильно? Тогда вы должны спросить себя, почему бы просто не менять его постоянно в магазине redux? Или наоборот.
Мне кажется, что здесь можно использовать redux store без состояния компонентов. OnMount отправляет действие для получения значения сервера, а onChange отправляет обновление значения в хранилище. Для отображаемого значения контролируйте это значением в хранилище redux





Поскольку вы отредактировали свой вопрос, стало более ясно, чего вы хотите достичь, поэтому я хочу заняться этим.
Вы можете сохранить состояние ваших контролируемых элементов ввода в компоненте, а затем использовать хранилище redux для хранения постоянных данных и заполнения значений по умолчанию.
class Component extends React.Component {
constructor(props) {
super(props)
this.state = {
aboutMe: props.aboutMe,
... // other data
}
}
handleSubmit = (event) => {
event.preventDefault() // To prevent redirect
// Dispatch the save user input action
this.props.dispatch(saveUserInput(this.state))
}
render() {
return (
<form onSubmit = {this.handleSubmit} />
<TextInput onTextChange = {text => this.setState({...this.state, aboutMe: text}) />
... // input fields for other data
// Clicking this fill trigger the submit event for the form
<button type = "submit">Save</button>
</form>
)
}
}
1) Если ваш компонент является управляемым компонентом (вам нужно состояние в нем) и запрос действительно асинхронный, вам нужно установить состояние в componentWillReceiveProps следующим образом:
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}
/>
);
}
}
Имейте в виду, что главное здесь в том, что государство должно оставаться единственным источником истины с этого момента.
2) Другой вариант: вы можете дождаться завершения запроса в родительском компоненте, а затем установить aboutMe в своем конструкторе, таким образом вы можете избежать componentWillReceiveProps. Например:
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}
/>
);
}
}
Обратной стороной этого является то, что введенный текст не будет отображаться до тех пор, пока запрос не будет завершен.
Ты спас мне день :)
вы не используете setState для изменения состояния вашего хранилища, вместо этого вы должны отправлять действия и обрабатывать действия соответствующим образом на ваших редукторах