Skip to content

Commit dd55f73

Browse files
committed
Flexible Lists in React
1 parent 52235c6 commit dd55f73

4 files changed

Lines changed: 43 additions & 58 deletions

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,6 @@ In this repository, I've implemented (or implementing) all the concepts related
4747
3. Affecting `state` from a generated List of Components
4848
1. Updating State Directly (*flawed approach, can lead to unknown behaviour of the apps*): [Commit Details](https://github.com/Ch-sriram/react/commit/91c6424f4bdce8b71542c0a6cdb396475c6adff7)
4949
2. Updating State Immutably (correction to the flawed approach) using `splice()` or `...` [Spread Operator]: [Commit Details](https://github.com/Ch-sriram/react/commit/0936c2c3b540f808a7139ec400bfe1dbab9de76e)
50-
4. Lists & Keys — using `key` prop: [Commit Details]()
50+
4. Lists & Keys — using `key` prop
51+
1. The *incorrect* way: [Commit Details](https://github.com/Ch-sriram/react/commit/52235c6906dfd14d20103adb78378881ac2c6b2d)
52+
2. The *correct* way \[making lists flexible\]: [Commit Details]()

react-examples/src/App.js

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,49 @@ import { Person } from './components/person/person.component';
55
class App extends Component {
66
state = {
77
persons: [
8-
{ name: 'Ram', age: 28 },
9-
{ name: 'Roop', age: 29 },
10-
{ name: 'Max', age: 28 }
8+
{ name: 'Ram', age: 28, id: 'a1' },
9+
{ name: 'Roop', age: 29, id: 'a2' },
10+
{ name: 'Max', age: 28, id: 'a3' }
1111
],
1212
otherState: "This has some value",
1313
showPersons: false
1414
}
1515

16-
nameChangedHandler = event => {
17-
this.setState({
18-
persons: [
19-
{ id: 'abc1', name: "Mar", age: 82 },
20-
{ id: 'abc2', name: event.target.value, age: 92 },
21-
{ id: 'abc3', name: "Xam", age: 82 },
22-
],
23-
});
16+
nameChangedHandler = (event, id) => {
17+
// we'll only update the state of the person for which
18+
// the input field was changed, and so, we first need to
19+
// find the index of the Person where the input field was
20+
// changed in the DOM
21+
22+
const personIndex = this.state.persons.findIndex(
23+
person => person.id === id
24+
);
25+
26+
// We can get the person we want to be modified from the
27+
// state now, but we DON'T want to get it the foll. way:
28+
29+
// const person = this.state.persons[personIndex]; // this will directly mutate the actual person in the state, which should not be done directly, only by the setState() method.
30+
31+
// In ES5:
32+
// const person = Object.assign({}, this.state.persons[personIndex]);
33+
34+
// In ES6:
35+
const person = { ...this.state.persons[personIndex] };
36+
37+
// now we're manipulating a copy of the original state
38+
person.name = event.target.value;
39+
40+
const personsList = [...this.state.persons];
41+
personsList[personIndex] = person;
42+
43+
this.setState({persons: personsList});
2444
}
2545

2646
deletePersonHandler = (personIndex) => {
27-
// DON'T DO THIS:
47+
// DON'T DO THIS, as this mutates the state directly
2848
// const personsList = this.state.persons;
2949

30-
// DO THIS:
50+
// DO THIS, as this mutates a copy of the state
3151
// const personsList = this.state.persons.slice();
3252
const personsList = [...this.state.persons];
3353
personsList.splice(personIndex, 1); // remove 1 element from starting from personIndex
@@ -48,41 +68,6 @@ class App extends Component {
4868
cursor: "pointer",
4969
};
5070

51-
/**
52-
* In React, we always have to have a key prop defined for
53-
* a component/element that's generated as a list. This
54-
* is not mandatory, but it is highly recommended because
55-
* of the way React renders lists. It compares the changes
56-
* of the list-items in the list with how they were before
57-
* the state change. This identification is done using the
58-
* `key` prop in React.
59-
*
60-
* The `key` prop for a component in the list can be any
61-
* unique identifier (numeric/alpha-numeric/etc), main
62-
* take-away being "unique". Two components in the same
63-
* list cannot have the same `key` prop, they definitely
64-
* should only have 1 unique key each.
65-
*
66-
* To maintain uniqueness of `key` prop, we can use the
67-
* index of the element in the array, but that's not a
68-
* good way to store keys as everything might not be
69-
* fetched from an array, they can also be fetched from
70-
* some API and the list-items need not be having an index.
71-
*
72-
* If the list-items are fetched from some API, then they
73-
* most definitely have some unique ID to identify each
74-
* item uniquely. For now, we might just define an 'id'
75-
* of our own for each Person, but that's just for the
76-
* demonstration of `key` props.
77-
*
78-
* We will see that we still get the following warning:
79-
* "Each child in a list should have a unique `key` prop."
80-
*
81-
* But why does this happen? We'll see what to do, in the
82-
* next commit.
83-
*/
84-
85-
8671
// we can always refer to JSX using simple JS variables
8772
let persons = null;
8873

@@ -96,6 +81,7 @@ class App extends Component {
9681
name={person.name}
9782
age={person.age}
9883
key={person.id}
84+
changed={event => this.nameChangedHandler(event, person.id)}
9985
/>
10086
);
10187
})}

react-examples/src/components/person/person.component.jsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,11 @@ export const Person = (props) => {
1818
<p onClick={props.click}>
1919
I'm {props.name} and I'm {props.age} years old!
2020
</p>
21-
{props.children ? (
22-
<div className="person__input">
23-
<p>{props.children}</p>
24-
<input type="text" onChange={props.changed}
25-
value={props.name}
26-
/>
27-
</div>
28-
) : null}
21+
<input
22+
type="text"
23+
onChange={props.changed}
24+
value={props.name}
25+
/>
2926
</div>
3027
);
3128
}

react-examples/src/components/person/person.style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
padding: 16px;
77
}
88

9-
.person .person__input > input[type=text] {
9+
.person input[type=text] {
1010
text-align: center;
1111
width: 30%;
1212
}

0 commit comments

Comments
 (0)