Omar Badran
Omar Badran

Reputation: 155

Why is ReactJs updating a global var?

I'm new to ReactJs and I really do not know how to explain this question to you, but I'm working on a react app, and I was trying to make a form generator component, and I created it successfully. but when I try to use it in any other component every thing starts to act in a weird way :( for example, it's updating a global var and I don't know how is this happening. My code :

fields.js

/**
 *
 * React component that render a control fields using a JSON schema.
 *
 * @file crezmo-fields.js
 * @summary React forms component
 * @author CREZMO <crezmo.com>
 *
 */
class CrezmoFields extends React.Component {

    /**
    * constructor.
    *
    * @since    1.0.0
    * @return   {void}
    */
    constructor (props){
        super(props);
        this.state = {
            fields : this.props.fields            
        };
        this.handleChange = this.handleChange.bind(this);
    }

    /**
    * Render.
    *
    * @since    1.0.0
    * @return   {ReactElement}
    */
    render (){
        return (
            <div>
                {this.state.fields.map((field , index)=>{

                    switch (field.type) {
                        case 'text' : {
                            console.log(this);
                            return this.TextField(field , index);
                            break;
                        }
                    }

                })}
            </div>
        )
    }


    /**
    * Handle Changes.
    *
    * @since    1.0.0
    * @return   {void}
    */
    handleChange (index , new_value){
        // Create an updated field object
        const updated_field = this.state.fields[index];
        updated_field.value = new_value;

        // Create an updated fields object
        const updated_fields = this.state.fields;
        updated_fields[index] = updated_field;

        // Update the component 
        this.setState({fields : updated_fields});

        // Pass data to parent
        (typeof(this.props.hasChanged) === "function" && this.props.hasChanged(this.state.fields))

    }


    /**
    * Text field.
    *
    * @since    1.0.0
    * @param    {object}        data - the field data.
    * @param    {number}        field index number in state.fields
    * @returns  {ReactElement}  a react element of the field
    */
    TextField = (data , index) => {
        const self = this;
        return (
            <div key={index} className={`cf-field cf-${data.type} cf-id-${data.id}`}>
                <label htmlFor={data.id}>
                    {data.title}
                </label>
                <div className="cf-control-wraper">
                    <input 
                        type='text'
                        placeholder = {data.placeholder}
                        name={data.id}
                        value={data.value}
                        onChange={
                            (e) => {
                                self.handleChange(index , e.target.value);
                            }
                        }
                    />
                </div>
                <span className="cf-field-desc">{data.description}</span>
            </div>
        )
    };

}

app.js

var fields = [ //why is this array getting updated when i type in the input field ? 
    {
        type : 'text',
        id : "my_id",        
    }
];

class TestForms extends React.Component {

    /**
    * constructor.
    *
    * @since    1.0.0
    * @return   {void}
    */
    constructor (props){
        super(props);
        this.state = {
            formfields: this.props.fields
        };
    }


    render (){
        return (
            <div>
                <CrezmoFields fields={this.state.formfields}
                    hasChanged={(state)=>{
                        this.setState({formfields: state})
                    }} 
                />
            </div>
        )
    }

}

ReactDOM.render(
    <TestForms fields={fields}/>,
    document.getElementById('app')
);

What i'm i missing ? Thanks in advance :)

Upvotes: 2

Views: 66

Answers (2)

Arber Sylejmani
Arber Sylejmani

Reputation: 2108

This has nothing to do with React actually, it is because, you are passing an array and objects/arrays are passed on by reference, so it means you are not passing a new array, instead you are mutating the initial array you passed because it is just passing down the reference of the array, not a new array. Fields itself is an array which is passed on reference but it also contains objects which are also passed on by reference. So nothing to do with React, just plain simple Javascript stuff :)

Upvotes: 2

SLaks
SLaks

Reputation: 887453

Because you never copy the array.

Javascript objects are passed by reference, so passing an object around will still mutate the original object.

Upvotes: 6

Related Questions