Skip to content

Commit 13265c1

Browse files
committed
DOM events in JSX & setState()'s async behaviour.
- How to get data from the user input in JSX. - Worked on App component, to get the input from user, and stored in state.searchField.
1 parent bbb0461 commit 13265c1

1 file changed

Lines changed: 110 additions & 25 deletions

File tree

monsters-rolodex/src/App.js

Lines changed: 110 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/**
22
* Learnings:
3-
* 1. How to send the state using props.
4-
* 2. Why should we make certain code specific to certain components.
5-
* 3. How to nest a component inside another component.
3+
* 1. Handling DOM events using JSX.
4+
* 2. How to get data from the user input in react.
5+
* 3. setState() function and its asynchronous behaviour.
66
*/
77

88
// Look into card-list.component.jsx to understand the comments.
@@ -22,6 +22,7 @@ class App extends Component {
2222
super(); // Calls React.Component's constructor() function
2323
this.state = {
2424
monsters: [],
25+
searchField: ""
2526
};
2627
}
2728

@@ -33,37 +34,121 @@ class App extends Component {
3334
}
3435

3536
/**
36-
* Earlier, we were just passing props.children in between
37-
* the div element inside the CardList component. The props.
38-
* children contained what we sent in this App component
39-
* into the CardList component.
37+
* The next component we want to add in, is our search
38+
* feature. That search feature is a text-box that takes in
39+
* text input and depending on the the text input, makes
40+
* sure that only those monster cards remain on the page.
4041
*
41-
* But in general, we never do that because right now, the
42-
* App component is responsible for rendering all the names
43-
* in the state (monster object). We never give that kind of
44-
* a responsibility to the App component, but we give that
45-
* kind of a responsibility to the CardList component
46-
* because that's how we separate concerns into components,
47-
* and also the CardList component should be responsible to
48-
* render the monsters' names in the first place.
42+
* To render a text-box on to the front-end, we will simply
43+
* use an input HTML element which is of type="search". On
44+
* top of that, we also want to take control of whatever the
45+
* user is typing into the search box and store it inside
46+
* our state. For that, we use the onChange event on the
47+
* input element as shown below. onChange is an event handler
48+
* that takes in a parameter called event which has the info
49+
* about which event has occurred.
4950
*
50-
* Therefore, what we do is, we send in the monster object
51-
* through to the CardList component as a prop as follows:
51+
* If we log the event object, we'd get details on the event
52+
* that has occurred. And if we want to get the element on
53+
* which the event is occurring, we'd just simply refer it
54+
* as event.target as shown below.
5255
*
53-
* <CardList monsters={this.state.monsters} />
56+
* To get the value that has been typed inside the search
57+
* box, we'd just get the value inside the target that's
58+
* being changed every time i.e., event.target.value;
59+
*/
60+
61+
// render() {
62+
// return (
63+
// <div className="App">
64+
// <input
65+
// type="search"
66+
// placeholder="search monsters"
67+
// onChange={event => {console.log(event.target.value)}}
68+
// />
69+
70+
// <CardList monsters={this.state.monsters} />
71+
// </div>
72+
// );
73+
// }
74+
75+
/**
76+
* Now, instead of logging the value in the event, we can
77+
* store the typed in text in our state inside our
78+
* searchField object.
5479
*
55-
* Now we can see that the functionality of generating the
56-
* names has been delegated to the CardList component (Look
57-
* into the CardList component for more information).
80+
* The state.searchField, when we log it onto the console,
81+
* we'd not see the immediate value being registered inside
82+
* it and that's because of the behaviour of the setState()
83+
* function, which is an asynchronous function.
84+
*/
85+
86+
// render() {
87+
// return (
88+
// <div className="App">
89+
// <input
90+
// type="search"
91+
// placeholder="search monsters"
92+
// onChange={event => {
93+
// this.setState({ searchField: event.target.value });
94+
// console.log(this.state);
95+
// }}
96+
// />
97+
98+
// <CardList monsters={this.state.monsters} />
99+
// </div>
100+
// );
101+
// }
102+
103+
/**
104+
* From the code above, we would get a weird behaviour which
105+
* is that, when we log the state, we would see that
106+
* searchField's value wouldn't be updated as soon as we log
107+
* it, and this happens because setState() function is an
108+
* asynchronous function. And so, if we want the perfect
109+
* searchField's value to be shown as soon as it is changed,
110+
* we'd have to send in a 2nd parameter to the setState()
111+
* function to which we send a callback function. The
112+
* callback runs after the setState() function has completed
113+
* its work. Therefore, we'd do it as follows:
114+
*/
115+
116+
// render() {
117+
// return (
118+
// <div className="App">
119+
// <input
120+
// type="search"
121+
// placeholder="search monsters"
122+
// onChange={event =>
123+
// this.setState({ searchField: event.target.value }, () => console.log(this.state))
124+
// }
125+
// />
126+
127+
// <CardList monsters={this.state.monsters} />
128+
// </div>
129+
// );
130+
// }
131+
132+
/**
133+
* Now we will see the correct output in the searchField,
134+
* being updated instantly after the state is changed, and
135+
* that's because we're passing a callback to the setState()
136+
* function in its 2nd parameter.
58137
*
59-
* Because of what we did, the App component need not worry
60-
* about rendering the monster cards, it will be taken care
61-
* by the CardList component.
138+
* Now, we just want to setState() i.e., set the value of
139+
* searchField after taking the input from the user.So for
140+
* that, we can get rid of the logging step altogether.
62141
*/
63-
142+
64143
render() {
65144
return (
66145
<div className="App">
146+
<input
147+
type="search"
148+
placeholder="search monsters"
149+
onChange={event => this.setState({ searchField: event.target.value })}
150+
/>
151+
67152
<CardList monsters={this.state.monsters} />
68153
</div>
69154
);

0 commit comments

Comments
 (0)