Free React Course
For Beginners

L5 - Tracking Changes

React For Beginners by Itera

Key Points

  • What is change detection
  • Implicit change detection with Angular
  • Explicit change detection with React
  • How it works in React (simplified)
  • Typical mistakes

What is change detection

Change detection - mechanism that tracks data changes and notifies appropriate listeners

As an example - look on the BtnWithCounter:

state = {counter: 0}
⬇️
Clicked 0 times
🖱️ Click
⬇️
setState({counter:1})
⬇️
Clicked 1 times

It looks very simple from the first sight but imagine:

  • Rich data
  • Rich user interaction
  • Backend interaction

🤯🤯🤯

Two ways to track changes

Implicit change detection strategy

Angular way

            class CalculatorService {
    income: number;
    setIncome(newIncome){
        this.income = newIncome;
    }
}

    
{{income}}

No special actions to inform framework that data changes

In Angular this works because of NgZone and patching all DOM events

Whenever something happens - click, network, input - Angular starts checking changes

React uses another way - explicit

With explicit way you have to somehow notify framework that data changes

Usually this achieved with using special methods

For class based components - setState

setState({})

For functional components - useState hook

const [counter, setCounter] = useState({});
setCounter(1);
        

Ok, we notified react that data changed. What next?

  • After the notification React will recalculate all components which
    • changed props
    • changed state
    • all child functional components for p.1 and p2
  • Build new Virtual DOM based on the results
  • Find the diff
  • Updates real DOM to match new Virtual DOM

Typical mistakes

💔 Ignoring state when data is subject to change

const data = { counter: 0 };
const MyBtn = () => {
    return <button onClick={() => (data.counter += 1)}>
        {data.counter}
    </button>;
};
            

💔 Mutating state directly, without special methods

const MyBtn = () => {
    const [data] = useState({ counter: 0 });
    return <button onClick={() => (data.counter += 1)}>
        {data.counter}
    </button>;
};
          

💔 Also applicable for Class based components

class MyBtn extends Component {
state = { counter: 0 };
render() {
    return (
        <button onClick={() => (this.state.counter += 1)}>
            {this.state.counter}
        </button>
    );}
}
          

💔 Mixing approach

Using this.setState() with functional components

Using useState with class-based components

If you data is supposed to change - use state and don't mutate it directly

  • setState for class components
  • useSate for functional components

Useful links