We covered a lot and we changed a lot of names, what if we want to change the name on our own.
So let’s that in the Person component. we also have an another element a normal input element, a normal input element which is type of text.
Person
input
import React from 'react'; const person = props => { return ( <div> <p onClick={props.click}> I am a {props.name} and i am {props.age} year old!{' '} </p> <p> {props.children} </p> <input type="text" /> {/* normal Input field */} </div> ); }; export default person;
Now whenever we type something in input we want to use what we type in input as a newName. Now for that we can listen to a special event onChange.
newName
onChange
onChange={} : we can listen to a special event on change. onChange will be fired whenever the value in the input changes.
onChange={}
... <input type="text" onChange={}/> ...
and there i dont want to execute some method which i need to pass down from our src/App.js file. We got that switch name handler and we will leave it as it is and instead add a new handler, will name as a nameChangedHandler which expect to get an event object that we haven’t used before, but in there I still want to change the state now of course theoretically you would want to change does it state or the name of the person for which we type this. This is something we’ll do it later in the course once we learned how to correctly render a list of dynamic elements.
nameChangedHandler
So for now i will always change the name in the App.js
... nameChangedHandler = (event) => { this.setState({ persons: [ { name: 'Lucy Stifert', age: 23 }, { name: event.target.value, age: 12 }, { name: 'Mike', age: 34 }, ], }); }; ...
So here will get an event, and as you might know for javascript events this event proably has a target, the target dosent make for a good name value through but the target should be the input into which we typed. So it should also have a value property which is of value the user entered and therefore this now makes for a good updated value for name. event.target.value iswhat We want to assign as a newName for manual. Again for time being no matter in which input of whch component is typed nameChangedHandler is a handler, Now We need to pass this to a component to be able to access it from Person.js. Since we only change Max We will only pass it to the menu person, though we could pass it to any other ofcourse.
value
event.target.value
Person.js
... render() { return ( <div className="App"> ... <Person name={this.state.persons[0].name} age={this.state.persons[0].age} /> <Person click={this.switchNameHandler} name={this.state.persons[1].name} age={this.state.persons[1].age} changed={this.nameChangedHandler} /> <Person name={this.state.persons[2].name} age={this.state.persons[2].age} /> </div> ); } ...
so we will simply name changed and will pass this.nameChangedHandler following the same logic for a click event. Inside the Person component we can access this changed property and simply call props.changed there. Dont add parentheses but simply pass the reference to it. and keep in props.changed refers to the method we declared in App.js the nameChangedHandler.
changed
this.nameChangedHandler
props.changed
import React from 'react'; const person = props => { return ( <div> <p onClick={props.click}> I am a {props.name} and i am {props.age} year old!{' '} </p> <p> {props.children} </p> <input type="text" onChange={props.changed}/> </div> ); }; export default person;
The event object will be passed to it automatically by React like a normal javascript where you all by default get access to the event object. With that let us save the code and see what happens in your browser. with that let’s save this and let us see what happens we got input below all components but for most of them, nothing happens. but if we change input below Max details the data gets updated. this is because we bound onChange to those props.changed which holds a reference to the nameChangedHandler and then we used the default event object to extract the target which is input element and then the value of the target which is what we entered. This show is two things how we can dynamically update something, dynamically call an event and use the things we learn before like passing down event references or method references but it all just shows us how we can handle inputs.
Now it would be nice if we would see the current value of the name in the input right from the start. So we want to set up two-way binding when we change it we want to propagate that change so that we can update the state but we also want to see the current state right from the start. To do that we can set value={props.name} this is the name after all.
value={props.name}
import React from 'react'; const person = props => { return ( <div> <p onClick={props.click}> I am a {props.name} and i am {props.age} year old!{' '} </p> <p> {props.children} </p> <input type="text" onChange={props.changed} value={props.name}/> </div> ); }; export default person;
And now we have our own two way binding setup. We listen to change, calls the method in end which refers to the nameChangedHandler which updates the state and then passed down the state to the Person with name and age and we output the name as the value of the input.
for now we can ignore console Warning ! message. We will improve this once we have a better way of dynamically rendering a list of elements