Событие onChange происходит только один раз, когда состоянием управляет redux

#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.

В данный момент вы:

  1. Извлекаем состояние Redux (через props) и копируем его в состояние вашего компонента в componentDidMount .
  2. Заполнение ваших входных данных value из реквизитов (из состояния Redux).
  3. Обновление состояния вашего локального компонента через 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.