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