Ace
Ace

Reputation: 1146

React hooks being called out of order

For some reason, it seems that the useMemo hook is executing before the useEffect hook, directly above it. I believe this is so because I am receiving an error:

TypeError: Cannot read property 'timestamp' of undefined

this error points to the datum.timestamp in the dependency array for the last useEffect hook and occurs whenever is_paused changes from false => true.

The problem as I see it, is that the useMemo hook is trying to get an item from an empty array, an array which should have been set by the useEffect before it.

I did some logging, and indeed, I see the log in the useMemo, but not the useEffect.

const [position, setPosition] = useState(MAX_HISTORY - 1);
const [data, setData] = useState<ExData[]>(new Array(MAX_HISTORY).fill({ content: {} }));
const paused_data_ref = useRef<ExData[]>([]);

useEffect(() => {
  const listener = (d: ExData) => {
    const new_data = data.slice(1);
    new_data.push(d);
    setData(new_data);
  };
  addListener(props.event_key, listener);
  return () => {
    removeListener(props.event_key);
  };
});

useEffect(() => {
  paused_data_ref.current = is_paused ? [...data] : [];
  if (is_paused) {
    console.log('copy data array');
  }
}, [is_paused, data]);

const datum = useMemo(() => {
  if (is_paused)
    console.log({
      position,
      data: paused_data_ref.current[position],
      arr: paused_data_ref.current
    });
  return is_paused ? paused_data_ref.current[position] : data[MAX_HISTORY - 1];
}, [is_paused, position, data]);

useEffect(() => {...}, [datum.timestamp])

Upvotes: 2

Views: 1676

Answers (1)

helloitsjoe
helloitsjoe

Reputation: 6529

You are correct, the function passed to useEffect is called after the function passed to useMemo.

According to the React docs:

The function passed to useEffect will run after the render is committed to the screen.

This means that all useEffect calls will happen after the other functions in your component (including a function passed to useMemo), even if the useEffect is placed earlier in the component.

https://reactjs.org/docs/hooks-reference.html

Upvotes: 5

Related Questions