The philosophy of React: A single source of truth
A core concept behind React is that every piece of data lives in only one place: the state of the lowest common ancestor of every component that needs to worry about it.
If two components need to know about a piece of data, that data should live in the state of their closest common parent. That parent component should pass the data down to its children as props. If necessary, that component can also expose a setter function to its children, allowing them to affect the data.
Let’s imagine a React app with five components in the following tree:
.--A--. | | .--B--. C | | D E
Component A is the root. A has two children: B and C. B has two further children, D and E.
Let’s say we have a piece of data X that only components D and E need to worry about. X should live in the state of component B, because B is the lowest-level component where the component itself and its children are the only components that need to know about X. Placing X in the state of A would be wasteful, because component C doesn’t need to know about X.
.--A--. | | | C .--B--. <------- X should live here, if | | D E .-- only D and E need to know about it ^ ^ | |_____|______|
Notice that even if component B never uses X directly, X should still live in B‘s state.
If we have a piece of data Y that components D and C need to worry about, then Y should live in the state of component A. Again, even though B never uses Y, it still receives Y from A as a prop, and passes it down to D as a prop.
.--A--. <---- Y should live here, if | | | C <---- only D and C need to know about it .--B--. | | | | D E | ^ | |____________|
If it turns out in the course of development that component C needs to worry about X after all, X should be moved to the state of component A (this is called lifting the state.) It is bad practice to leave X in the state of B and then have component C use references to retrieve X from B, because C won’t be notified if B‘s state is updated and X changes.