Estoy tratando de enviar una acción de Redux desde un enlace personalizado con useDispatch, pero recibo el error "Llamada de enlace no válida". Si entiendo correctamente las reglas de los ganchos, no creo que esté infringiendo ninguna de las reglas, ya que estoy llamando a useDispatch desde un gancho personalizado. ¿¿Qué me estoy perdiendo??
CÓDIGO
Selector principal para componente funcional
export const getFlattenedDevicesList = createSelector( getDevicesList, (deviceList) => { return ( deviceList .map(makeOrganizationKey) .map(makeProjectKey) .map(makeDeviceProfileKey) .map(DispatchLSU) // custom hook ); } );Gancho personalizado
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; }; El objetivo es enviar la acción para cada entrada en deviceList y luego insertar nuevos datos de la llamada API.
Este código está rompiendo las reglas de los ganchos, solo llame a los ganchos de React Functions .
Probablemente esté llamando a getFlattenedDevicesList con useSelector , luego dentro de esto llama a DispatchLSU que llama a useDispatch .
Entonces tienes un gancho dentro de un gancho que recibe una devolución de llamada:
useSelector -> getFlattenedDevicesList -> DispatchLSU -> useDispatch
Si desea llamar a dispatch y su selector dentro de un gancho. Aquí está cómo lograrlo
export function DispatchLSU() { const dispatch = useDispatch(); const resource = useSelector(getFlattenedDevicesList); const deviceId = resource.device_id; useEffect(() => { dispatch(getHealthLsu(deviceId)); }, []); const result = { ...resource, }; return result; };useXXXuseDispatch o useCallback para evitar hacer un envío cuando renderizadeviceId del dispositivo.Su problema es que getFlattenedDevicesList es una función normal y una función normal no puede llamar a un enlace. Los ganchos solo se pueden llamar desde el nivel superior de 1. un componente de reacción o 2. otro gancho. Puede convertir getFlattenedDevicesList en un gancho usando otro gancho dentro de él, pero solo puede hacerlo en el nivel superior.
es decir
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 } }El punto de entrada o la raíz desde donde comienza a llamar a ese gancho, junto con toda la cadena de ganchos a la que puede o no estar llamando, debe ser un componente o un gancho.
Ejemplo:
const example = () => {}Esa es una función normal, no un gancho.
const useExample = () => {}Esa es una función JS normal, no un gancho.
const useExample = () => { const [value, setValue] = useState() }Ese es un gancho personalizado ya que está usando otro gancho, reaccionar se dará cuenta de que también debe ser un gancho.
const example = () => { const [value, setValue] = useState() }Ese también es exactamente el mismo gancho personalizado que el anterior y funcionará exactamente igual que el gancho anterior, simplemente se llama diferente.
Si quieres encadenar ganchos:
const useHook1 = () => { const [value, setValue] = useState() return {value, setValue} } const useHook2 = () => { const {value, setValue} = useHook1() return {value} } Eso es válido porque cualquier gancho también puede llamar a otro gancho, tal como lo hizo al usar useState .
Sin embargo, si ahora desea usar useHook2 en algún lugar , debe llamarse desde otro enlace o un componente funcional.
es decir
const Component = (): JSX.Element => { const {value} = useHook2() }Es válida.
Sin embargo, si intenta llamar a useHook1 o useHook2 desde cualquier función normal o cualquier cosa que no sea un gancho o un componente de función, se romperá.
Para arreglarlo puedes hacer algo como:
const useDispatch = () => { const dispatch = (resource) => { // do whatever here } return dispatch } const useExample = () => { const dispatch = useDispatch() dispatch(// resource) } Nota: El nombre del gancho es irrelevante, puedes llamarlo como quieras. React descubrirá que es un gancho basado en el hecho de que está usando otros ganchos o algo como useState . Sin embargo, se recomienda encarecidamente que le agregue el prefijo use , es decir, useSomeHook , porque 1. facilita que otros desarrolladores vean qué es un gancho y qué es una función normal y 2. muchas herramientas como eslint se construyen alrededor de un use el prefijo para aplicar reglas de enganche y validaciones, por lo que si no lo nombra con "usar", esas cosas no funcionarán correctamente.