staticCoffee staticCoffee - 15 days ago 6
Javascript Question

Using React components to edit objects and render said changes?

I'm trying to write a simple RPG to learn more about how data can be manipulated in JS/React and become more familiar with the language. Currently, I have a simple form taking input, and changing an object. The object is named

person
and I'm trying to change his name.

var person = {
name: ''
}


Here is the component that handles the object change:

class ChangePersonProp extends React.Component {
constructor() {
super();
this.state = {value: ''};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}

handleChange(event) {
this.setState({value: event.target.value});
}

handleSubmit() {
if (this.props.buttonTitle == 'Name') {
person.name = this.state.value;
}
}

render() {
return(
<form onSubmit={this.handleSubmit}>
<label>
{this.props.buttonTitle + ': '}
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit"/>
</form>
);
}
}


However, I cannot seem to show these changes to the user. I suspect it is due to the
Root
component re-rendering on the change to the form, and not updating the object properly. I assume this is true because the console doesn't log the change on
render
.

class Root extends React.Component {
render() {
console.log(person.name)
if (player.name == '') {
return(
<div>
<ChangePlayerProp buttonTitle="Name" />
</div>
);
}else {
return(
<div>
<p>{person.name}</p>
</div>
);
}
}
}


How would I go about structuring my
Root
component to show changes to the
person
object?

Answer

Live Demo

Above is a working example, below is how it's structured, however in your case this isn't really the correct approach. The below code just has the pertinent pieces. Basically I pass a function down as a prop to the ChangePersonProp component. It then calls that function when submitting, which updates the data in the Root components state allowing it to rerender. However like I said I don't really think this is the correct approach, this is a short term fix that would get extremely messy fast.

code you shouldnt pay too much attention to

class ChangePersonProp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: ''};
    }
    handleSubmit() {
        if (this.props.buttonTitle == 'Name') {
            this.props.onSubmit(this.state.value);
        }
    }
}

class Root extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: ''
        }
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    render() {
        if (!this.state.name) {
            return(
              // things
            );
        }

      return(
         // other things instead
      );
    }
    handleSubmit(value) {
        this.setState({name : value});
    }
}


ReactDOM.render(
  <Root/>,
  document.getElementById('container')
);

Proposed approach

The actual approach you would want to take is to use

  • flux (there are many implementations such as reflux)
  • redux (which isn't TECHNICALLY flux and why I'm including it)
  • or mobx which currently is my personal favorite.

You basically need something outside of the component hierarchy because you need non related components to know about the data and react to changes in the data.This is the exact use-case for flux or other implementations.

Here is some psuedocode on how it might look.

datastore {
    person = {all the properties}
}
dataStoreActions {
    changeName(name) {
        person.name = name;
    }
}

PersonInputComponent {
    // listens to store if it needs to react to any changes from it.

   // onSubmit calls the changeName action
}

RootComponent {
    // listens to store
    // Store has changed, so do something with the data.
}

Each implementation has their own approach for listening to stores, or calling actions so it really depends on what library you choose, but the overall approach is very similar between them all.

I know some smart people watch this tag so there might be some more fleshed out answers at some point but hopefully this is enough to get you going.

Comments