#node.js #reactjs #react-redux #onchange #react-redux-form
#node.js #reactjs #реагировать-redux #onchange #реагировать-redux-формировать
Вопрос:
Я извлекаю массив с одним объектом из хранилища redux.
this.props.license :[0: {id: 24, domain: "xyz.com", app_url: "https...", purchase_code: "395"}]
А затем создается форма для обновления значения в форме react.
Но при попытке изменить значение onChange
событие происходит только один раз.
Я управляю новым состоянием в компоненте react, чтобы сохранить изменения, которые я делаю в onChange
событии.
Это правильный способ, которым я кодирую?
import React ,{Component} from 'react';
import {connect} from 'react-redux';
import * as actionCreators from '../../store/actions/index';
import Spinner from '../../components/Spinner/Spinner';
const DATABASE_LABELS={
id:'ID',
domain:'Domain',
app_url:'APP URL',
purchase_code:'Purchase Code',
}
class editLicense extends Component {
constructor(props){
super(props);
this.state={
editLicense:{}
}
}
onChangeHandler=(event, type)=>{
// [event.target.name]=[event.target.value]
let newLicense={...this.state.editLicense}
newLicense[type]=event.target.value
console.log(newLicense)
console.log('before',this.state.editLicense)
this.setState({
editLicense :{
...this.state.editLicense,
[event.target.name]:event.target.value
}
})
console.log(this.state.editLicense)
}
componentDidMount=()=>{
this.props.viewLicenceDetails(this.props.token, this.props.match.params.id)
this.setState({
editLicense:this.props.licenses[0]
})
console.log(this.state.editLicense)
}
render(){
let formdata=<Spinner/>;
if(!this.props.loading){
let license=Object.keys(this.props.licenses[0])
.map(key=>{
return [
key,
this.props.licenses[0][key]
]
})
let form=license.map((p, index)=>{
return(
<div className="form-group" key={p[0]}>
<label htmlFor={p[0]}> {DATABASE_LABELS[p[0]]} </label>
<input type="text" className="form-control"
id={p[0]}
value={p[1]}
name={p[0]}
onChange={(event) => this.onChangeHandler(event, p[0])} />
</div>)
})
formdata=(
<form>
{form}
<button type="submit" className="btn btn-primary">Submit</button>
</form>
)
}
return(
<div className="container">
{formdata}
</div>
)}
}
const mapStateToProps = (state)=>{
return({
token:state.auth.idToken,
licenses:state.license.licenses,
loading:state.license.loading,
err:state.license.error
})
}
const mapDispatchToProps = dispatch=>{
return({
updateLicenseData:(token, type, newVal)=>dispatch(actionCreators.updateLicense(token, type, newVal)),
viewLicenceDetails:(token, id)=>dispatch(actionCreators.fetchOneLicense(token, id))
})
}
export default connect(mapStateToProps, mapDispatchToProps)(editLicense);
Комментарии:
1. где вы используете
this.state.editLicense
?
Ответ №1:
Название вопроса немного вводит в заблуждение. В настоящее время ваше состояние не полностью управляется Redux, а только изначально извлекается из состояния Redux.
В данный момент вы:
- Извлекаем состояние Redux (через props) и копируем его в состояние вашего компонента в
componentDidMount
. - Заполнение ваших входных данных
value
из реквизитов (из состояния Redux). - Обновление состояния вашего локального компонента через
onChange
->onChangeHandler
.
(2) ваша проблема в настоящее время. Ваши реквизиты в настоящее время не изменяются (поскольку вы не вызываете никаких действий Redux), поэтому значение вашего input
элемента никогда не меняется. Это немного неинтуитивно, но это приводит к тому, что изменения обнаруживаются только один раз.
Вам нужно заполнить свой входной value
реквизит, используя ваше состояние. В вашей render()
функции попробуйте заменить экземпляры this.props.licenses[0]
на this.state.editLicense
:
if(!this.props.loading){
let license=Object.keys(this.state.editLicense)
.map(key=>{
return [
key,
this.state.editLicense[key]
]
})
...
}
Таким образом, когда ваше состояние обновляется, «текущее» значение формы будет обновлено при повторной визуализации, и input
компонент будет полностью контролироваться.
В качестве дополнительного примечания:
this.setState({
editLicense:this.props.licenses[0]
})
console.log(this.state.editLicense)
Это не гарантирует работу. setState
обычно следует считать асинхронным. Если вы хотите что-то сделать в ответ на обновленное состояние вне цикла рендеринга, вы должны предоставить обратный вызов setState
:
this.setState({
editLicense:this.props.licenses[0]
},
() => console.log(this.state.editLicense)
);
Комментарии:
1. Спасибо, Дилан Уокер! 🙂 Ваше решение сработало нормально. У меня есть один вопрос относительно «Извлечения состояния Redux (через props) и копирования его в состояние вашего компонента в componentDidMount». . Является ли это правильным подходом для обновления состояния компонента из выбранного состояния redux?
2. @RitaBala Это немного зависит от вашего предполагаемого шаблона. Если вы просто хотите установить свое начальное состояние из своего состояния Redux, внести кучу промежуточных изменений (таких как редактирование вашей формы), а затем «отправить» обновленное состояние позже с помощью действия Redux, тогда ваш подход подходит. Однако, если вы ожидаете, что что-то другое изменит ваше состояние Redux и хотите, чтобы ваша форма обновлялась, чтобы отразить это в том же жизненном цикле, я бы вообще избегал использования состояния компонента и строго использовал состояние Redux.