useState()
. import React, { useState } from 'react'; function Example() { const [state, setState] = useState({counter:0}); const add1ToCounter = () => { const newCounterValue = state.counter + 1; setState({ counter: newCounterValue}); } return ( <div> <p>You clicked {state.counter} times</p> <button onClick={add1ToCounter}> Click me </button> </div> ); }
componentDidMount()
. The useEffect()
hook allows you to do the same in functional components. // useEffect(() => { console.log(' '); }); // useEffect(() => { console.log(' valueA'); }, [valueA]);
componentDidMount()
, we will pass an empty array with the second parameter. Since the contents of an empty array always remain the same, the effect will be executed only once. // useEffect(() => { console.log(' '); }, []);
getState()
, all subscribing components call their own getState()
and are updated due to this.useState()
inside our custom hook. But instead of returning the setState()
function, we add it to the listeners array and return a function that internally updates the state object and calls all the listeners. npm install -s use-global-hook
import { useState, useEffect } from 'react'; let listeners = []; let state = { counter: 0 }; const setState = (newState) => { state = { ...state, ...newState }; listeners.forEach((listener) => { listener(state); }); }; const useCustom = () => { const newListener = useState()[1]; useEffect(() => { listeners.push(newListener); }, []); return [state, setState]; }; export default useCustom;
import React from 'react'; import useCustom from './customHook'; const Counter = () => { const [globalState, setGlobalState] = useCustom(); const add1Global = () => { const newCounterValue = globalState.counter + 1; setGlobalState({ counter: newCounterValue }); }; return ( <div> <p> counter: {globalState.counter} </p> <button type="button" onClick={add1Global}> +1 to global </button> </div> ); }; export default Counter;
initialState
with parameters;useEffect(function, [])
with an empty array works the same way as componentDidMount()
. But if the function passed in the first parameter returns another function, then the second function will be called right before unmounting the component. Just like componentWillUnmount()
. const useCustom = () => { const newListener = useState()[1]; useEffect(() => { // listeners.push(newListener); return () => { // listeners = listeners.filter(listener => listener !== newListener); }; }, []); return [state, setState]; };
initalState
;store
object that will contain the state
value and the setState()
function;setState()
and useCustom()
so that you can associate the store
with this
. function setState(newState) { this.state = { ...this.state, ...newState }; this.listeners.forEach((listener) => { listener(this.state); }); } function useCustom(React) { const newListener = React.useState()[1]; React.useEffect(() => { // this.listeners.push(newListener); return () => { // this.listeners = this.listeners.filter(listener => listener !== newListener); }; }, []); return [this.state, this.setState]; } const useGlobalHook = (React, initialState) => { const store = { state: initialState, listeners: [] }; store.setState = setState.bind(store); return useCustom.bind(store, React); }; export default useGlobalHook;
setState()
, but to a set of actions.useGlobalHook(React, initialState, actions)
third argument. Just want to add a couple of comments.store
. Thus, actions can read the contents of store.state
, update the store.setState()
calling store.setState()
and even call other store.actions
by store.actions
.actions.addToCounter(amount
) to a sub-object with all the actions of the counter: actions.counter.add(amount)
.use-global-hook
package. function setState(newState) { this.state = { ...this.state, ...newState }; this.listeners.forEach((listener) => { listener(this.state); }); } function useCustom(React) { const newListener = React.useState()[1]; React.useEffect(() => { this.listeners.push(newListener); return () => { this.listeners = this.listeners.filter(listener => listener !== newListener); }; }, []); return [this.state, this.actions]; } function associateActions(store, actions) { const associatedActions = {}; Object.keys(actions).forEach((key) => { if (typeof actions[key] === 'function') { associatedActions[key] = actions[key].bind(null, store); } if (typeof actions[key] === 'object') { associatedActions[key] = associateActions(store, actions[key]); } }); return associatedActions; } const useGlobalHook = (React, initialState, actions) => { const store = { state: initialState, listeners: [] }; store.setState = setState.bind(store); store.actions = associateActions(store, actions); return useCustom.bind(store, React); }; export default useGlobalHook;
useGlobalHook.js
. Now you can focus on your application. Below are two examples of using the package.Source: https://habr.com/ru/post/454348/
All Articles