目錄:
  1. 基础Hook
    1. useState
      1. useEffect
        1. useContext
        2. 额外的 Hook
          1. useReducer
            1. useCallback
              1. useMemo
                1. useRef
                  1. useImperativeHandle
                    1. useLayoutEffect
                      1. useDebugValue
                      2. 使用React.memo实现shouldComponentUpdate

                        Redex-Hooks

                        閱讀時間:全文 882 字,預估用時 5 分鐘
                        創作日期:2019-10-24
                        文章標籤:
                        下篇文章:Redex-Hooks
                         
                        BEGIN

                        Hook API是React 16.8的新特性, 可以让我们可以在函数组件中使用state及其它特性.

                        基础Hook

                        useState

                        生成state值与修改state值的函数, 传入默认值, 返回值与操作函数.

                        使用方式: const [state, setState] = useState(initialState);

                        useEffect

                        用于模拟类组件的componentDidMountcomponentDidUpdatecomponentWillUnmount生命周期

                        useEffect传入两个参数, 第一个参数传入副作用函数, 模拟componentDidMountcomponentDidUpdate, 函数再返回的函数则相当于生命周期componentWillUnmount执行. 第二个参数传入参数组成的数组, 当值不同时才执行副作用函数, 当传入[]时表示副作用只执行一次.

                        使用如下:

                        useEffect(
                          () => {
                            something();
                            return () => {
                              something();
                            }
                          },
                          [a]
                        )

                        useContext

                        用于返回祖先组件最近的 <MyContext.Provider>value prop

                        使用方式: const theme = useContext(ThemeContext);

                        示例

                        const themes = {
                          light: {
                            foreground: "#000000",
                            background: "#eeeeee"
                          },
                          dark: {
                            foreground: "#ffffff",
                            background: "#222222"
                          }
                        };
                        
                        const ThemeContext = React.createContext(themes.light);
                        
                        function App() {
                          return (
                            <ThemeContext.Provider value={themes.dark}>
                              <Toolbar />
                            </ThemeContext.Provider>
                          );
                        }
                        
                        function Toolbar(props) {
                          return (
                            <div>
                              <ThemedButton />
                            </div>
                          );
                        }
                        
                        function ThemedButton() {
                          const theme = useContext(ThemeContext);
                        
                          return (
                            <button style={{ background: theme.background, color: theme.foreground }}>
                              I am styled by theme context!
                            </button>
                          );
                        }

                        额外的 Hook

                        useReducer

                        useState的替代方案, 有点像redux的理念, 使用时传入三个参数, 返回state值与操作函数.

                        使用方式: const [state, dispatch] = useReducer(reducer: (state: T, action: {}) => T, initialArg: T, init: (state: T) => T);

                        示例:

                        function init(initialCount) {
                          return {count: initialCount};
                        }
                        
                        function reducer(state, action) {
                          switch (action.type) {
                            case 'increment':
                              return {count: state.count + 1};
                            case 'decrement':
                              return {count: state.count - 1};
                            case 'reset':
                              return init(action.payload);
                            default:
                              throw new Error();
                          }
                        }
                        
                        function Counter({initialCount}) {
                          const [state, dispatch] = useReducer(reducer, initialCount, init);
                          return (
                            <>
                              Count: {state.count}
                              <button
                                onClick={() => dispatch({type: 'reset', payload: initialCount})}>
                        
                                Reset
                              </button>
                              <button onClick={() => dispatch({type: 'decrement'})}>-</button>
                              <button onClick={() => dispatch({type: 'increment'})}>+</button>
                            </>
                          );
                        }

                        useCallback

                        用于比对传入的数据值, 值变更时执行副作用

                        使用方式: const memoizedCallback = useCallback(callback: () => void, [params]);

                        示例(测量 DOM 节点):

                        function MeasureExample() {
                          const [height, setHeight] = useState(0);
                        
                          const measuredRef = useCallback(node => {
                            if (node !== null) {
                              setHeight(node.getBoundingClientRect().height);
                            }
                          }, []);
                        
                          return (
                            <>
                              <h1 ref={measuredRef}>Hello, world</h1>
                              <h2>The above header is {Math.round(height)}px tall</h2>
                            </>
                          );
                        }

                        将示例抽象成自定义Hook

                        function MeasureExample() {
                          const [rect, ref] = useClientRect();
                          return (
                            <>
                              <h1 ref={ref}>Hello, world</h1>
                              {rect !== null &&
                                <h2>The above header is {Math.round(rect.height)}px tall</h2>
                              }
                            </>
                          );
                        }
                        
                        function useClientRect() {
                          const [rect, setRect] = useState(null);
                          const ref = useCallback(node => {
                            if (node !== null) {
                              setRect(node.getBoundingClientRect());
                            }
                          }, []);
                          return [rect, ref];
                        }

                        useMemo

                        记住上一次的计算结果, 当传入的依赖数组值没有发生变化则返回上一次返回的值

                        使用方式: const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

                        示例:

                        function Parent({ a, b }) {
                          // Only re-rendered if `a` changes:
                          const child1 = useMemo(() => <Child1 a={a} />, [a]);
                          // Only re-rendered if `b` changes:
                          const child2 = useMemo(() => <Child2 b={b} />, [b]);
                          return (
                            <>
                              {child1}
                              {child2}
                            </>
                          )
                        }

                        useRef

                        返回一个引用对象, 传入初始值, 值保存在Ref引用的current中

                        使用方式: const refContainer: { current: any } = useRef(initialValue: any);

                        示例(使用useRef获取上一次渲染的state):

                        function Counter() {
                          const [count, setCount] = useState(0);
                        
                          const prevCountRef = useRef();
                          useEffect(() => {
                            prevCountRef.current = count;
                          });
                          const prevCount = prevCountRef.current;
                        
                          return <h1>Now: {count}, before: {prevCount}</h1>;
                        }

                        将示例抽象成自定义Hook

                        function Counter() {
                          const [count, setCount] = useState(0);
                          const prevCount = usePrevious(count);
                          return <h1>Now: {count}, before: {prevCount}</h1>;
                        }
                        
                        function usePrevious(value) {
                          const ref = useRef();
                          useEffect(() => {
                            ref.current = value;
                          });
                          return ref.current;
                        }

                        useImperativeHandle

                        用于将子组件的引用暴露给父组件使用, 需要和forwardRef配合使用

                        示例:

                        function FancyInput(props, ref) {
                          const inputRef = useRef();
                          useImperativeHandle(ref, () => ({
                            focus: () => {
                              inputRef.current.focus();
                            }
                          }));
                          return <input ref={inputRef} ... />;
                        }
                        FancyInput = forwardRef(FancyInput);

                        useLayoutEffect

                        使用方式与useEffect相同, 唯一区别是, useEffect在DOM渲染结束后执行, 而useLayoutEffect与DOM渲染同步执行

                        useDebugValue

                        useDebugValue 用于在 React 开发者工具中显示自定义 hook 的标签

                        使用React.memo实现shouldComponentUpdate

                        FINISH
                        下篇文章:Redex-Hooks

                        隨機文章
                        人生倒計時
                        default