Компонент не перерисовывается после изменения состояния - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть интерфейс с двумя командами кнопок (функции и цели).Когда я нажимаю на кнопку, я хочу, чтобы одна команда перешла к другой команде.Я реализую это с реакцией и избыточностью.Моя единственная проблема заключается в том, что когда состояние обновляется, и я успешно сохраняю в журнале обновленное состояние, компонент не будет работать, если я не использую forceUpdate ().Что я не понимаю, так это то, что, поскольку состояние обновляется успешно, не должен ли компонент автоматически перерисовываться?

Some.js

class Some extends React.Component{

    constructor(props){
        super(props)
        this.state = {
            selectedFeatures:[],
            selectedTargets:[]
        }
    }

    setStateFromProps(){
        this.setState({
            selectedFeatures: this.props.features,
            selectedTargets: this.props.targets,
        }, console.log(this.state.selectedFeatures, this.state.selectedTargets))
    }

    componentDidMount(){
        this.setStateFromProps()
    }

    render(){

        const { features, targets} = this.props

        const updateLists =(selectedFeature, flag) =>{
            let index
            if  (flag){
                index = features.indexOf(selectedFeature)
                features.splice(index, 1);

                targets.push(selectedFeature)

                this.props.addFeature({features, targets})
            }else{
                index = targets.indexOf(selectedFeature)
                targets.splice(index, 1);

                features.push(selectedFeature)
                this.props.addFeature({targets, features})
            }

            console.log(this.state.selectedFeatures, this.state.selectedTargets)


        }

        return (
            <div>
                {this.state.selectedFeatures.map(feature => {

                    return <div><button key={feature} onClick={() => updateLists(feature, true)}>{feature}</button> <br /></div>
                })}
                <br />
                {this.state.selectedTargets.map(target => {
                    return <div><button key={target} onClick={() =>updateLists(target, false)} >{target}</button> <br /></div>
                })}
            </div>
        );

    }
}

const mapDispatchToProps =(dispatch) =>{
    return {
            addFeature: (data) => dispatch(featureAddedToTargets(data)),
        }
} 
const mapStateToProps= (state)=>{
    return { selectedFeature:state.addFeatureReducer.selectedFeature,
            features: state.addFeatureReducer.features,
            targets: state.addFeatureReducer.targets
    };
}


export default connect(mapStateToProps, mapDispatchToProps)(Some);

Как вы можете видеть, Когда я нажимаю накнопка Я запускаю функцию updateLists, которая заставит вычисление изменить отправку на наше единственное действие новых данных с обновленной функцией и целевыми кнопками, и действие изменит состояние в редукторе.

Действие featureAddedToTargets

    export const featureAddedToTargets = (data) =>{
        return {
            type: FEATURE_CHANGED,
            data
        }
    }

addFeatureReducer

    const initialState = {
        features:['f1','f2','f3','f4','f5'],
        targets:['t1','t2']
    }

    const addFeatureReducer = (state=initialState, action) =>{
        switch(action.type){
            case FEATURE_CHANGED:
                console.log("action: ", action)
                return {...state , state, features: action.data.features, targets: action.data.targets};
            default: 
                return state;
        }
    }
export default combineReducers({ addFeatureReducer })

Как я уже говорил, компонент Some не выполняет повторную визуализацию, а команда кнопок остается неизменной, даже если в initialState в редукторе изменились и, следовательно, реквизиты.Некоторые компоненты также изменились.Я хочу понять, почему это происходит.

введите описание изображения здесь

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019
setStateFromProps(){
        this.setState({
            selectedFeatures: this.props.features,
            selectedTargets: this.props.targets,
        }, console.log(this.state.selectedFeatures, this.state.selectedTargets))
    }

попробуйте изменить это на

    componentDidUpdate(prevProps) {
        if(this.props.features !== prevProps.features || this.props.targets !== prevProps.targets) {
      this.setState({
            selectedFeatures: this.props.features,
            selectedTargets: this.props.targets,
        }, console.log(this.state.selectedFeatures, this.state.selectedTargets))
    }

}
0 голосов
/ 05 февраля 2019

Итак, я понял, почему компонент не обновлялся, хотя состояние обновлялось.Похоже, что в updatedLists () я использовал push () и splice () непосредственно для массива объектов и целевых объектов в хранилище избыточностей, таким образом изменяя мое состояние.Из-за мутации компонент не видел изменений в текущем и следующем состоянии.React хранит в памяти две версии состояния - текущую и следующую.Он сравнивает два и обновляет DOM только с частями, которые изменились.Из-за того, что я изменял состояние, React видел и текущий, и следующий как одинаковые, поэтому он не обновлялся.Поэтому я просто изменил updatedLists (), я применил push () и splice () к случайным переменным (Features and Targets), которые позже я передал в качестве данных нашему действию, передав их значения с помощью оператора распространения (как мы делали раньше) всостояние магазина (initialState).

if  (flag){
            index = this.state.selectedFeatures.indexOf(selectedFeature)
            const Features = [...this.state.selectedFeatures]
            Features.splice(index, 1);

            const Targets = [...this.state.selectedTargets]
            Targets.push(selectedFeature)

            console.log('features',features,'targets',targets)
            this.props.addFeature({features: Features , targets: Targets})
        }else{
            index = this.state.selectedTargets.indexOf(selectedFeature)
            const Targets = [...this.state.selectedTargets]
            Targets.splice(index, 1);

            const Features = [...this.state.selectedFeatures]
            Features.push(selectedFeature)

            console.log('features',features,'targets',targets)
            this.props.addFeature({ features:Features, targets: Targets})
        }
0 голосов
/ 05 февраля 2019

После запуска действия FEATURE_CHANGED ваш редуктор возвращает обновленное состояние, которое, в свою очередь, передается через mapStateToProps в ваш React Component как newProps.В функции рендеринга вы отображаете на this.state.selectedFeatures и this.state.selectedTargets.Из того, что я вижу, похоже, что, хотя вы получаете новые Props features и targets, вы не обновляете их в состоянии вашего компонента.Вы можете использовать getDerivedStateFromProps жизненный цикл для обновления состояния по мере поступления новых реквизитов.

getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.features !== prevState.features && nextProps.targets !== prevState.targets) {
        return ({
           selectedFeatures: nextProps.features,
           selectedTargets: nextProps.targets
        });
    }
    else if (nextProps.features !== prevState.features) {
       return ({
           selectedFeatures: nextProps.features,
        });
    } else if (nextProps.targets !== prevState.targets) {
       return ({
           selectedTargets: nextProps.targets,
        });
    }
}

Вы можете сослаться на это здесь: https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...