--description--
Your application may have more complex interactions between state
and the rendered UI. For example, form control elements for text input, such as input
and textarea
, maintain their own state in the DOM as the user types. With React, you can move this mutable state into a React component's state
. The user's input becomes part of the application state
, so React controls the value of that input field. Typically, if you have React components with input fields the user can type into, it will be a controlled input form.
--instructions--
The code editor has the skeleton of a component called ControlledInput
to create a controlled input
element. The component's state
is already initialized with an input
property that holds an empty string. This value represents the text a user types into the input
field.
First, create a method called handleChange()
that has a parameter called event
. When the method is called, it receives an event
object that contains a string of text from the input
element. You can access this string with event.target.value
inside the method. Update the input
property of the component's state
with this new string.
In the render
method, create the input
element above the h4
tag. Add a value
attribute which is equal to the input
property of the component's state
. Then add an onChange
property set to the handleChange()
event handler method.
When you type in the input box, that text is processed by the handleChange()
method, set as the input
property in the local state
, and rendered as the value in the input
box on the page. The component state
is the single source of truth regarding the input data.
Last but not least, don't forget to add the necessary bindings in the constructor.
--hints--
ControlledInput
should return a div
element which contains an input
and a p
tag.
assert(
Enzyme.mount(React.createElement(ControlledInput))
.find('div')
.children()
.find('input').length === 1 &&
Enzyme.mount(React.createElement(ControlledInput))
.find('div')
.children()
.find('p').length === 1
);
The state of ControlledInput
should initialize with an input
property set to an empty string.
assert.strictEqual(
Enzyme.mount(React.createElement(ControlledInput)).state('input'),
''
);
Typing in the input element should update the state and the value of the input, and the p
element should render this state as you type.
async () => {
const waitForIt = (fn) =>
new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 250));
const mockedComponent = Enzyme.mount(React.createElement(ControlledInput));
const _1 = () => {
mockedComponent.setState({ input: '' });
return waitForIt(() => mockedComponent.state('input'));
};
const _2 = () => {
mockedComponent
.find('input')
.simulate('change', { target: { value: 'TestInput' } });
return waitForIt(() => ({
state: mockedComponent.state('input'),
text: mockedComponent.find('p').text(),
inputVal: mockedComponent.find('input').props().value
}));
};
const before = await _1();
const after = await _2();
assert(
before === '' &&
after.state === 'TestInput' &&
after.text === 'TestInput' &&
after.inputVal === 'TestInput'
);
};
--seed--
--after-user-code--
ReactDOM.render(<ControlledInput />, document.getElementById('root'))
--seed-contents--
class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
// Change code below this line
// Change code above this line
}
// Change code below this line
// Change code above this line
render() {
return (
<div>
{ /* Change code below this line */}
{ /* Change code above this line */}
<h4>Controlled Input:</h4>
<p>{this.state.input}</p>
</div>
);
}
};
--solutions--
class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
input: event.target.value
});
}
render() {
return (
<div>
<input
value={this.state.input}
onChange={this.handleChange} />
<h4>Controlled Input:</h4>
<p>{this.state.input}</p>
</div>
);
}
};