React.js在渲染子类时无意中重用了data-reactid

ags*_*ala 3 javascript reactjs

我有一个Questionnaire渲染几个QuestionnaireOption子类的对象.QuestionnaireOption当父Questionnaire对象中的状态发生更改时,将呈现新的子类.

QuestionnaireOption如果"选择"与否类维护状态.

问题:当我更改父类中的状态以呈现新的"选项"节点时,新节点被分配相同data-reactid,我希望选项节点重置其内部状态但是没有分配新的ID和它包含错误的状态(在这种情况下,selected尽管道具设置了新数据,但仍然在新对象上设置为true).

我该怎么做才能解决这个问题?

这是相关的代码:

QuestionnaireOption = React.createClass({
    getInitialState: function() {
        return {selected: false}
    },
    handleClick: function(e) {
        e.preventDefault();
        this.setState({selected: !this.state.selected});
    },
    render: function() {
        var fullClassName = "questionnaireOption " + (this.state.selected? "selected": "unselected");
        return (
            <div className='questionnaireOptionWrapper large-4 small-4 columns'>
                <div className={fullClassName} onClick={this.handleClick}>
                    <div>{this.props.name}</div>
                </div>
            </div>
        );
    }
});

Questionnaire = React.createClass({
    getInitialState: function() {
        return {currentStage: 0}
    },
    saveOptionState: function() {
        // dump option state into amber.js or localstorage
    },
    advanceWizard: function() {
        this.saveOptionState();
        this.setState({currentStage: this.state.currentStage + 1});
    },
    rewindWizard: function() {
        this.saveOptionState();
        this.setState({currentStage: this.state.currentStage - 1});
    },
    seeResults: function() {
        console.log(globalOptionState);
    },
    render: function() {
        var currentWizardQuestion = wizardQuestions[this.state.currentStage];
        var currentOptionNodes = currentWizardQuestion.options.map(function(option) {
            node = (
                <QuestionnaireOption
                    name={option.name}
                    value={option.value}
                />
            );
            return node;
        });

        return (
            <div className="questionnaire row">
                <div className="questionnaire-question large-8 small-12 columns">
                    <div className="questionnaire-question-text">
                        {currentWizardQuestion.text}
                    </div>
                    <div className="questionnaire-question-subtext">
                        {currentWizardQuestion.subtext}
                    </div>
                    <div className="row">
                        {currentOptionNodes}
                    </div>

                    <input type="button" value="Back" onClick={this.rewindWizard}
                        style={this.state.currentStage == 0? {display: "none"}: {}
                    } />

                    <input type="button" value="Next" onClick={this.advanceWizard}
                        style={this.state.currentStage == wizardQuestions.length - 1?
                            {display: "none"}: {}
                    } />

                    <input type="button" value="Finish" onClick={this.seeResults}
                        style={this.state.currentStage < wizardQuestions.length - 1?
                            {display: "none"}: {}
                    } />
                </div>
            </div>
        );
    }
});
Run Code Online (Sandbox Code Playgroud)

Bri*_*and 6

在您的控制台中,您有此警告:

数组中的每个子节点都应该具有唯一的"键"支柱.检查App的渲染方法.有关更多信息,请参见fb.me/react-warning-keys.

如果你不这样做,你就不会使用开发版本:你应该解决这个问题.

React使用两件事来确定渲染之间是否有"相同":组件类(例如QuestionnaireOption)和关键道具.

如果其中一个与前一个渲染不匹配,则react认为它不同,并重新创建实例*并丢弃子树dom.

假设option.name可用于确定相等性,请将代码更改为:

    var currentOptionNodes = currentWizardQuestion.options.map(function(option) {
        var node = (
            <QuestionnaireOption
                name={option.name}
                value={option.value}
                key={option.name}
            />
        );
        return node;
    });
Run Code Online (Sandbox Code Playgroud)

作为参考,reactid是一个实现细节,可以随时更改或删除.

*如果您只是更改项目的顺序,它将尝试仅更改性能的顺序.目前有一些情况不会发生这种情况,所以不应该依赖它.