在孙子上反应改变道具:对象不可扩展/树遍历会对孩子做出反应

时间:2015-11-16 18:06:48

标签: javascript reactjs

我正在关注教程,无法运行以下代码。 当我运行以下代码时,我收到错误Can't add property attachToForm, object is not extensible。您是否不再允许以这种方式更改子道具(即使用child.props.key = value)?如果没有,你能看到一个更好的方法,只有当元素是输入时才向嵌套子项添加函数吗?

React.Children.forEach(children, function (child) {
    if (child.props.name) {

    child.props.attachToForm = this.attachToForm;
        child.props.detachFromForm = this.detachFromForm;
    }
    if (child.props.children) {
        this.registerInputs(child.props.children);
    }
}.bind(this));

我正在使用es6,如果它改变了什么,但可以在这里找到教程:http://christianalfoni.github.io/javascript/2014/10/22/nailing-that-validation-with-reactjs.html

FormComponent:

'use strict';

import React from 'react';
import BaseComponent from '@client/base-component';

export default class Form extends BaseComponent {

    constructor(props) {
        super(props);
        this.state = {};
    }

    render() {
        var classString = this.props.className ? this.props.className : '';
        var classArray = ['_common-form', this.props.type ? 'form--' + this.props.type :  'form--basic' ];

        for(var i = 0; i < classArray.length; i++){
            if(classArray[i]){
                classString = classString + ' ' +classArray[i];
            }
        }

        var props = {
            type: this.props.type,
            className: classString,
            style: this.props.style,
            onSubmit: this.props.onSubmit
        };

        return React.createElement(
            'form', 
            props, 
            this.newChildren
        );
    }

    componentWillMount() {
        this.inputs = {}; 
        this.model = {}; 
        this.newChildren = [];
        this.registerInputs(this.props.children);
    }

    registerInputs(children) {
        React.Children.forEach(children, function (child) {
            if (child.props.name) {
                child.props.attachToForm = this.attachToForm;
                child.props.detachFromForm = this.detachFromForm;
            }
            if (child.props.children) {
                this.registerInputs(child.props.children);
            }
        }.bind(this));
    }


    attachToForm(component) {
        this.inputs[component.props.name] = component;
        this.model[component.props.name] = component.state.value;
    }

    detachFromForm(component) {
        delete this.inputs[component.props.name];
        delete this.model[component.props.name];
    }

}

ModalComponent:

'use strict';

import React from 'react';
import Modal from '@client/common/modal';
import Button from '@client/common/buttons';
import AddParticipant from './add_participant'; 
import Form from '@client/common/form_elements';
import Input from '@client/common/form_elements/input.js';
import SlideToggle from '@client/common/form_elements/slide_toggle.js';
import FormField from '@client/common/form_elements/form_field.js';
import FormSection from '@client/common/form_elements/section.js';
import BaseComponent from '@client/base-component'; 

export default class EditTeam extends BaseComponent {

    constructor(props) {
        super(props);
        this.state = { 
            values: {
                name: props.team.name,
                mission: props.team.mission,
                globalSearch: props.team.globalSearch,
                public: props.team.public,
                witcryptSecured: props.team.witcryptSecured
            },
            addParticipantModal: false
        };
    }

    render() {
        var participantsList = [];

        this.props.team.participants.forEach(function(participant) {
            participantsList.push(
                <div className="participant" key={participant.key}>
                    <span className="participant-avatar" style={{backgroundImage:`url("${participant.avatar}")`}}></span>
                    <span>{participant.name}</span>
                    <span className={`${participant.roll}-action roll`}>{participant.roll}<a></a></span>
                </div>
            );
        }.bind(this));

        return ( 
            <Modal className="_common-edit-team-settings" title={`Edit ${this.props.team.name}`} isOpen={this.props.modalIsOpen && this.props.editTeamModal} onCancel={this.props.toggleEditTeamModal} backdropClosesModal>

                <Form onSubmit={this.saveChanges}>      
                    <FormSection className="edit-team-details" sectionHeader="Team Details">
                        <FormField label="Name">
                            <Input name="name" value={this.state.values.name} onChange={this.handleInputChange} type="text" placeholder={this.props.team.name}/>
                        </FormField>
                        <FormField label="Mission">
                            <Input name="mission" value={this.state.values.mission} onChange={this.handleInputChange} type="text" placeholder={this.props.team.kitMission || 'Kit Mission'} multiline />
                        </FormField>
                    </FormSection>

                    <FormSection className="privacy-settings" sectionHeader="Privacy Settings">
                        <FormField label="Included in global search results" >
                            <SlideToggle name="globalSearch" defaultChecked={this.state.values.globalSearch} onChange={this.handleCheckedChange} type="checkbox" />
                        </FormField>
                        <FormField label="Accessible by anyone" >
                            <SlideToggle name="public" defaultChecked={this.state.values.public} onChange={this.handleCheckedChange} type="checkbox" />
                        </FormField>
                        <FormField label="Secured with WitCrypt" >
                            <SlideToggle name="witcryptSecured" defaultChecked={this.state.values.witcryptSecured} onChange={this.handleCheckedChange} type="checkbox" />
                        </FormField>
                    </FormSection>
                    <FormSection sectionHeader="Participants">
                        {participantsList}
                        <div id="add-participant" className="participant" onClick={this.toggleAddParticipantModal}>
                            <span className="participant-avatar" style={{backgroundImage:'url(/img/blue_add.svg)'}}></span>
                            <span>Add a Participant</span>
                            <span className="add-action roll"><a></a></span>
                        </div>
                    </FormSection>
                    <Button type="hollow-primary" size="md" className="single-modal-btn" block submit>Save</Button>
                </Form>


                <AddParticipant people={this.props.people} toggleAddParticipantModal={this.props.toggleAddParticipantModal} modalIsOpen={this.props.modalIsOpen} toggleAddParticipantModal={this.toggleAddParticipantModal} addParticipantModal={this.state.addParticipantModal} />
            </Modal>
        );
    }

    toggleAddParticipantModal() {
        this.setState({
            addParticipantModal: !this.state.addParticipantModal
        });
    }

    handleCheckedChange(event){
        var newState = this.state;
        newState.values[event.target.name] = !newState.values[event.target.name];
        this.setState(
            newState
        );
    }

    handleInputChange(event){
        var newState = this.state;
        newState.values[event.target.name] = event.target.value;
        this.setState(
            newState
        );
    }

    saveChanges(e){
        e.preventDefault(); 
    }

}

1 个答案:

答案 0 :(得分:31)

您使用的是React v.14或更高版本吗?道具对象is now frozen并且无法更改。您可以使用React.cloneElement代替