状态数组中的更改不会通过props更改子项

时间:2017-12-24 21:25:01

标签: javascript

最近,我一直在使用动态控制输入文本框,每个文本框都有自己的id。但是,我注意到如果我存储了一个元素数组,并且每个元素都是一个具有不同变量的对象,那么对象中这些变量的任何更改都不会提示React更新子组件(通过props接收状态) )。我试图根据文档控制输入,但我很困惑为什么普通非数组和非对象变量的父状态的变化将被孩子识别为道具的变化而不是对于普通状态数组。这是我的父代码:

import React, {Component} from 'react';
import Music from './music'
import axios from 'axios';
import update from 'immutability-helper';

class Selection {
    constructor(){
        this.music = '';
        this.beginning = '';
        this.the_end = '';
    }
    setTitle=(title)=>{
        this.music = title;
    }
    setStart=(start)=>{
        this.beginning = start;
    }
    setEnd=(end)=>{
        this.the_end = end;
    }
}

class Practice extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            selections: Array(0),
            test: 0,
        }
        this.removeSong = this.removeSong.bind(this);
    }
    removeSong(index){
        var newArray = this.state.selections.slice();
        newArray.splice(index, 1);
        this.setState({selections: newArray, test: this.state.test+=1});

    }
    addAnotherSong=()=>{
        var newArray = this.state.selections.slice();
        newArray.push(new Selection());
        this.setState({ selections: newArray, test: this.state.test+=1});

    }

    render(){

        return(
            <div>
                <button onClick={() => this.props.practice()}>Log Practice Session</button>
                <h1>{this.props.time}</h1>
                <form >
                        Description: <input type="form" placeholder="How did it go?" name="fname"/><br/>
                </form>
                <button onClick={()=>this.addAnotherSong()}>Add Another Piece</button>
                <button onClick={()=>this.setState({test: this.state.test})}>Will it now Update?</button>
                {
                    this.state.selections.map((child, index) => (
                            this.state.selections[index].music,
                            <Music key={index} number={index} subtract={this.removeSong}
                            Title={this.state.test} Start={this.state.selections[index].beginning}
                            End={this.state.selections[index].the_end} changeTitle={this.state.selections[index].setTitle}
                            changeStart={this.state.selections[index].setStart} changeEnd={this.state.selections[index].setEnd}
                            />

                    ))
                }
            </div>

        );
    }
}

export default Practice;

如您所见,我在状态中有一个数组,其中包含从Selection类构造的对象。以下是不会更新的子项,除非更改发生在非数组类型&#34; this.state.test&#34;丙

import React, {Component} from 'react';
import InputBox from './input';
class Music extends React.Component{
    constructor(props){
        super(props);
    }
    shouldComponentUpdate(newProps){
        if(this.props !== newProps){
            return true;
        } else{
            console.log("wassup");
            return false;
        }
    }
    render(){
        return(
        <div>{this.props.number}
            <InputBox cValue={this.props.Title} identity={this.props.number} updateInput={this.props.changeTitle} />
            <InputBox cValue={this.props.Start} identity={this.props.number} updateInput={this.props.changeStart} />
            <InputBox cValue={this.props.End} identity={this.props.number} updateInput={this.props.changeEnd} />
            <button onClick={()=> this.props.subtract(this.props.number)}>DELETE{this.props.number}</button>
            {this.props.Title}
        </div>
        )
    }
}
export default Music;

最后,这是孩子的孩子。

import React,{Component} from 'react';

class InputBox extends React.Component{
    constructor(props){
        super(props);
        this.state = { value: '' }
        this.handleChange = this.handleChange.bind(this);
    }
    handleChange(event){
        this.setState({value: event.target.value});
        this.props.updateInput(this.state.value, this.props.identity);
        console.log("test" + this.props.cValue);
    }
    shouldComponentUpdate(newProps){
        if(this.props !== newProps){
            console.log("Updating Input Component");
            return true;
        } else {
            console.log("yo");
            return false;

        }
    }
    render(){

        return(
            <input type="text"onChange={this.handleChange} value={this.props.cValue}/>
        )
    }
}
export default InputBox;

如果这是一个不好的问题,请告诉我。但是,任何帮助总是受到赞赏。三江源

1 个答案:

答案 0 :(得分:1)

你将你的状态视为一个可变对象 - React中的状态永远不应该被改变,状态改变应该永远是一个全新的对象。

例如,我们在Selection中只有一个state.selections

[ { music: 'music', beginning: 'beginning', the_end: 'ending' } ]

如果Music组件最终调用setStart('newBeginning'),那么我们最终会在我们的状态中结束:

[ { music: 'music', beginning: 'newBeginning', the_end: 'ending' } ]

这个看起来就像一切顺利一样,但默认情况下React实际上不会接受此更改,因为state.selections仍然引用到同一个数组。

要修复它,您必须在修改单个项目时弄清楚如何更新阵列引用。您已在removeSongaddAnotherSong中通过在当前状态下调用slice完成此操作。 Slice返回一个新数组,因此没有问题。

我建议您使用Selection修改单个Practice的方法,而不是修改每个Selection

这样的事情可行:

   class Practice extends React.Component{
        updateSelectionBeginning(index, newBeginning){
            var newArray = this.state.selections.slice();
            newArray[index].beginning = newBeginning;
            this.setState({selections: newArray});
        }
    }

然后我们会通过道具将它传递给我们的孩子,他们会打电话给updateSelectionBeginning(FOO, BAR)。这让我们可以更新状态,同时保持不变。