dai-shi / react-hooks-global-state

[NOT MAINTAINED] Simple global state for React with Hooks API without Context API

Home Page:https://www.npmjs.com/package/react-hooks-global-state

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Dispatch inside useEffect does not update state the first time

pongsatt opened this issue · comments

Problem: global state does not update when dispatch from inside useEffect the first time.

Example:

import * as React from 'react';
import { createStore } from 'react-hooks-global-state';

type State = { items: string[], loading: boolean }
type Action = { type: 'loadItems', items: string[] }
  | { type: 'loading', loading: boolean };

const reducer = (state: State, action: Action) => {
  switch (action.type) {
    case 'loadItems': return { ...state, items: action.items }
    case 'loading': return { ...state, loading: action.loading }
    default: return state;
  }
}

const initialState: State = { items: [], loading: false };
const { GlobalStateProvider, useGlobalState, dispatch } = createStore(reducer, initialState);

const loadInitialCount = async () => {
  dispatch({type: 'loading', loading: true});
  return new Promise<string[]>(resolve => setTimeout(() => resolve(['item1', 'item2']), 3000))
  .then(items => {
    dispatch({type: 'loading', loading: false});
    dispatch({type: 'loadItems', items});
  });
}

const ItemList = () => {
  const [items] = useGlobalState('items');
  const [loading] = useGlobalState('loading');

  React.useEffect(() => {
    loadInitialCount();
  }, []);

  if (loading) return <span>Loading...</span>;

  return (
    <>
      <button onClick={loadInitialCount}>reload</button>
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
    </>
  );
};

export default () => {
  return (
    <GlobalStateProvider>
      <ItemList />
    </GlobalStateProvider>);
};

When "loadInitialCount()" is called the first time, "Loading..." won't show up. But it's shown when click "reload" button.

I found that this is because "GlobalStateProvider" registers listener inside "useEffect" which is called after "useEffect" of "ItemList" component . So the "loading" state is not updated the first time.

@pongsatt Good catch! I confirmed the issue.

@pongsatt Published v0.4.0. Thanks for reporting!