tdranv
tdranv

Reputation: 1340

Calling dispatch from useEffect

I have the following custom hook:

export const useCurrentUser = () => {
  const dispatch = useDispatch();
  const user = useSelector(currentUserSelector);
  const preferredLanguage = useMemo(() => getUserAttribute(user, "preferred_language") || "en",
    [currentUser]
  );

  useEffect(() => {
    dispatch(loadAttributes(preferredLanguage));
  }, [preferredLanguage, dispatch]);

  return { preferredLanguage };
};

And this redux action:

const _getDefaultAttributes = async dispatch => {
  try {
    const res = await axios.get("www.api.com/attr.json");
    // receive omitted...
  } catch (err) {
    dispatch(failureAttributes(err));
  }
};

export const loadAttributes = (lang = null) => async dispatch => {
  if (!lang) {
    dispatch(_getDefaultAttributes());
    return;
  }

  try {
    const res = await axios.get(`www.api.com/attr-${lang}.json`);
    // receive omitted...
  } catch {
    _getDefaultAttributes(dispatch);
  }
};

The problem I have is that it makes about 40 requests. First loadAttributes() is called with en for lang, the api returns an error, since it does not have attributes for en, then it defaults to loading the default attributes. Here is a screenshot of the Network tab:

enter image description here

Any idea what is causing this?

Upvotes: 3

Views: 119

Answers (1)

Nadia Chibrikova
Nadia Chibrikova

Reputation: 5036

It is a common assumption that custom hooks can be used to share state between components, but actually they are not much more than normal javascript functions. The code inside a hook will behave in the exact same manner as if it was placed inside the component that is using it. This means that all useState and useEffect calls will be executed independently by each component instance (by all 40 component instances in this case :) ).

Upvotes: 1

Related Questions