Monday, 8 April 2019

Is it safe to call react hooks based on a constant condition?

The Rules of Hooks require that the same hooks and in the same order are called on every render. And there is an explanation about what goes wrong if you break this rule. For example this code:

function App() {
  console.log('render');
  const [flag, setFlag] = useState(true);
  const [first] = useState('first');
  console.log('first is', first);
  if (flag) {
    const [second] = useState('second');
    console.log('second is', second);
  }
  const [third] = useState('third');
  console.log('third is', third);

  useEffect(() => setFlag(false), []);

  return null;
}

Outputs to console

render 
first is first 
second is second 
third is third 
render 
first is first 
third is second 

And causes a warning or an error.

But what about conditions that do not change during the element lifecycle?

const DEBUG = true;

function TestConst() {
  if (DEBUG) {
    useEffect(() => console.log('rendered'));
  }

  return <span>test</span>;
}

This code doesn't really break the rules and seems to work fine. But it still triggers the eslint warning.

Moreover it seems to be possible to write similar code based on props:

function TestState({id, debug}) {
  const [isDebug] = useState(debug);

  if (isDebug) {
    useEffect(() => console.log('rendered', id));
  }

  return <span>{id}</span>;
}

function App() {
  const [counter, setCounter] = useState(0);
  useEffect(() => setCounter(1), []);
  return (
    <div>
      <TestState id="1" debug={false}/>
      <TestState id="2" debug={true}/>
    </div>
  );
}

This code works as intended.

So is it safe to call hooks inside a condition when I am sure that it is not going to change? Is it possible to modify the eslint rule to recognise such situations?

The question is more about the real requirement and not the way to implement similar behaviour. As far as I understand it is important to

ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls

And there is a place for exceptions to this rule: "Don’t call Hooks inside loops, conditions, or nested functions".



from Is it safe to call react hooks based on a constant condition?

No comments:

Post a Comment