Estaba experimentando con la nueva función Hook en React. Teniendo en cuenta que tengo los siguientes dos componentes (usando React Hooks):
const HookComponent = () => { const [username, setUsername] = useState('Abrar'); const [count, setState] = useState(); const handleChange = (e) => { setUsername(e.target.value); } return ( <div> <input name="userName" value={username} onChange={handleChange}/> <p>{username}</p> <p>From HookComponent: {count}</p> </div> ) } const HookComponent2 = () => { const [count, setCount] = useState(999); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } Los ganchos afirman resolver el problema de compartir la lógica con estado entre los componentes, pero descubrí que los estados entre HookComponent y HookComponent2 no se pueden compartir. Por ejemplo, el cambio de count en HookComponent2 no representa un cambio en HookComponent .
¿Es posible compartir estados entre componentes usando el gancho useState() ?
Si se refiere al estado del componente, los ganchos no lo ayudarán a compartirlo entre los componentes. El estado del componente es local para el componente. Si su estado vive en contexto, entonces useContext hook sería útil.
Fundamentalmente, creo que no entendiste la línea "compartir lógica con estado entre componentes". La lógica con estado es diferente del estado. La lógica con estado es algo que haces que modifica el estado. Por ejemplo, un componente que se suscribe a una tienda en componentDidMount() y cancela la suscripción en componentWillUnmount() . Este comportamiento de suscripción/cancelación de suscripción se puede implementar en un gancho y los componentes que necesitan este comportamiento pueden simplemente usar el gancho.
Si desea compartir el estado entre los componentes, hay varias formas de hacerlo, cada una con sus propios méritos:
Levante el estado hasta un componente ancestral común de los dos componentes.
function Ancestor() { const [count, setCount] = useState(999); return <> <DescendantA count={count} onCountChange={setCount} /> <DescendantB count={count} onCountChange={setCount} /> </>; }Este enfoque de compartir el estado no es fundamentalmente diferente de la forma tradicional de usar el estado, los ganchos simplemente nos brindan una forma diferente de declarar el estado del componente.
Si los descendientes están demasiado abajo en la jerarquía de componentes y no desea pasar el estado a demasiadas capas, puede usar la API de contexto .
Hay un useContext que puede aprovechar dentro de los componentes secundarios.
Bibliotecas de gestión de estado como Redux o Mobx. Su estado vivirá en una tienda fuera de React y los componentes pueden conectarse/suscribirse a la tienda para recibir actualizaciones.
Es posible sin ninguna biblioteca de gestión de estado externa. Simplemente use una implementación observable simple:
function makeObservable(target) { let listeners = []; // initial listeners can be passed an an argument aswell let value = target; function get() { return value; } function set(newValue) { if (value === newValue) return; value = newValue; listeners.forEach((l) => l(value)); } function subscribe(listenerFunc) { listeners.push(listenerFunc); return () => unsubscribe(listenerFunc); // will be used inside React.useEffect } function unsubscribe(listenerFunc) { listeners = listeners.filter((l) => l !== listenerFunc); } return { get, set, subscribe, }; } Y luego cree una tienda y conéctela para que reaccione usando subscribe en useEffect :
const userStore = makeObservable({ name: "user", count: 0 }); const useUser = () => { const [user, setUser] = React.useState(userStore.get()); React.useEffect(() => { return userStore.subscribe(setUser); }, []); const actions = React.useMemo(() => { return { setName: (name) => userStore.set({ ...user, name }), incrementCount: () => userStore.set({ ...user, count: user.count + 1 }), decrementCount: () => userStore.set({ ...user, count: user.count - 1 }), } }, [user]) return { state: user, actions } } Y eso debería funcionar. No es necesario React.Context o levantar el estado
Esto es posible usando el gancho useBetween .
import React, { useState } from 'react'; import { useBetween } from 'use-between'; const useShareableState = () => { const [username, setUsername] = useState('Abrar'); const [count, setCount] = useState(0); return { username, setUsername, count, setCount } } const HookComponent = () => { const { username, setUsername, count } = useBetween(useShareableState); const handleChange = (e) => { setUsername(e.target.value); } return ( <div> <input name="userName" value={username} onChange={handleChange}/> <p>{username}</p> <p>From HookComponent: {count}</p> </div> ) } const HookComponent2 = () => { const { count, setCount } = useBetween(useShareableState); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } Movemos la lógica con estado de los ganchos de React de HookComponent a useShareableState . Llamamos a useShareableState usando useBetween en cada componente.
useBetween es una forma de llamar a cualquier gancho. Pero para que el estado no se almacene en el componente React. Para el mismo gancho, el resultado de la llamada será el mismo. Entonces podemos llamar a un gancho en diferentes componentes y trabajar juntos en un estado. Al actualizar el estado compartido, cada componente que lo use también se actualizará.
Descargo de responsabilidad: soy el autor del paquete use- use-between .