Reputation: 155
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
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
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