A React component may need a value when it is first created, such as an ID for an image or a starting value for a counter. An initializer calculates or supplies that value at the start of the component’s lifetime. The appropriate pattern depends on whether the component is a class or a function. section 4.4.4 section 5.2.2
Listing 4.16 Gallery v4 using classes (excerpt)
...
class Image extends Component {
constructor(props) {
super(props); #1
this.id =
`image-${Math.floor(Math.random() * 1000000)}`; #2
}
render() {
return (
<figure style={{ margin: "5px" }} id={this.id}> #3
<img
src={`//picsum.photos/id/${this.props.index}/150/150/`}
alt={this.props.title}
/>
<figcaption>
<h3>Species: {this.props.title}</h3>
</figcaption>
</figure>
);
}
}
...
In this class component, `constructor(props)` calls `super(props)` and saves a generated ID as `this.id`. Rendering uses that same ID rather than generating another one. section 4.4.4
A class constructor runs once when the component is created, not whenever it re-renders. It suits data that should stay the same throughout that component’s lifetime. Store the generated ID on the instance, not in `this.props`: props are passed into the component and cannot be modified. Do not use the constructor to recalculate a value that must follow later prop changes. section 4.4.4
Initialize state without repeating expensive work
A password input can start with a generated password, then keep whatever the user types. `useState(generatePassword())` calls the generator on every render, although React uses that result only for the initial state. Pass the function instead: `useState(generatePassword)`. If it needs an argument, use `useState(() => generatePassword(12))`. Changing a prop used as an initial state value does not, by itself, reset that state. section 5.2.2
A function component has no class constructor. For the gallery’s stable calculated ID, the functional version uses `useMemo` with an empty dependency array. Take care when the desired state value is itself a function: `useState(OPERATORS.ADDITION)` treats it as an initializer and calls it. Use `useState(() => OPERATORS.ADDITION)` to store the function instead. section 4.4.4 section 5.2.2








