Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

206
Visualizações
How to use selectors and dispatch with a custom hook?

I'm trying to dispatch a Redux action from a custom hook with useDispatch but I'm getting an "Invalid hook call" error. If I'm understanding the rules of hooks correctly, I don't think I'm breaking any of the rules as I'm calling useDispatch from a custom hook. What am I missing??

CODE

Main selector for functional component

export const getFlattenedDevicesList = createSelector(
  getDevicesList,
  (deviceList) => {
    return (
      deviceList
        .map(makeOrganizationKey)
        .map(makeProjectKey)
        .map(makeDeviceProfileKey)
        .map(DispatchLSU) // custom hook
    );
  }
);

Custom hook

export function DispatchLSU(resource) {
  const dispatch = useDispatch();
  console.log(resource.device_id);
  const deviceId = resource.device_id;
  // useEffect(() => {
  //   dispatch(getHealthLsu(deviceId));
  // });
  dispatch(getHealthLsu(deviceId));

  const result = {
    ...resource,
  };

  return result;
};

The goal is to dispatch the action for each entry in deviceList then insert new data from API call.

about 4 years ago · Santiago Gelvez
2 Respostas
Responde à pergunta

0

Hooks rule: Only Call Hooks from React Functions

This code is breaking hooks rules, Only Call Hooks from React Functions.

You are probably calling getFlattenedDevicesList with useSelector then inside of this you call DispatchLSU who call useDispatch.

So you have a hook inside a hook that takes a callback:

useSelector -> getFlattenedDevicesList -> DispatchLSU -> useDispatch

How to call a selector and dispatch with hooks ?

If you want to call dispatch and your selector inside a hook. Here is how to achieve it

export function DispatchLSU() {
  const dispatch = useDispatch();
  const resource = useSelector(getFlattenedDevicesList);
  const deviceId = resource.device_id;
  useEffect(() => {
    dispatch(getHealthLsu(deviceId));
  }, []);

  const result = {
    ...resource,
  };

  return result;
};

Additional notes

  • Convention is to name custom hooks with useXXX
  • Instead of dispatching inside the hook method, you can use useDispatch or useCallback to avoid making a dispatch when you render
  • Instead of having a selector that return all resources you can have another one that return only the deviceId
about 4 years ago · Santiago Gelvez Relatório

0

Your issue is that getFlattenedDevicesList is a normal function and a normal function can not call a hook. Hooks can only be called from the top level of either 1. a react component or 2. another hook. You can convert getFlattenedDevicesList to a hook by using another hook inside it, but then you can only do so at the top level.

i.e.

const getFlattenedDevicesList = () => {
  // you can only use hooks here

  if (true) {
    // you can't use hooks here
    // or anywhere that's not at top level of getFlattenedDevicesList
  }
}

The entrypoint or root of where you start calling that hook from, along with the entire hook chain it may or may not be calling, must be either a component or a hook.

Example:

const example = () => {}

That is a normal function, not a hook.

const useExample = () => {}

That is a normal JS function, not a hook.

const useExample = () => {
  const [value, setValue] = useState()
}

That's a custom hook since it's using another hook, react will figure out that it needs to be a hook as well.

const example = () => {
  const [value, setValue] = useState()
}

That's also exactly the same custom hook as above and will work exactly the same as the hook above, it's just called different.

If you want to chain hooks:

const useHook1 = () => {
  const [value, setValue] = useState()

  return {value, setValue}
}

const useHook2 = () => {
  const {value, setValue} = useHook1()

  return {value}
}

That's valid because any hook can also call another hook, just like you did when using useState.

However if you now want to use useHook2 somewhere that has to be called from another hook or a functional component.

i.e.

const Component = (): JSX.Element => {
  const {value} = useHook2()
}

Is valid.

However if you try to call useHook1 or useHook2 from any normal function or anything that's not a hook or a function component it will break.

To fix it you can do something like:

const useDispatch = () => {
  const dispatch = (resource) => {
    // do whatever here
  }

  return dispatch
}

const useExample = () => {
  const dispatch = useDispatch()

  dispatch(// resource)
}

Note: The naming of the hook is irrelevant, you can call it anything you want. React will figure out it's a hook based on the fact that it's using other hooks or something like useState. However it is strongly recommended that you do prefix it with use, i.e. useSomeHook, because 1. it makes it easy for other developers to see what is a hook and what's a normal function and 2. a lot of tools like eslint is built around a use prefix in order to apply hook rules and validations so if you don't name it with "use" those things will not work correctly.

about 4 years ago · Santiago Gelvez Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda