React Hooks 总结

1:useState

import React, { useState } from 'react';

function App() {
  const [ Switch, setSwitch ] = useState("打开!");
  const newName = () => {
    Switch === "打开"? setSwitch("关闭"):setSwitch("打开");
  }
  return (
    <div>
      <p>现在是:{ Switch } 状态</p>
      <button onClick={ newName }>Change Me!</button>
    </div>
  );
}

export default App;

 多个参数处理

const [state, setState] = useState({ text: "", checked: false });

const updateState = partialState =>
    setState(oldState => ({
      ...oldState,
      ...partialState
}));

return (
    <div>
        <input
            type="checkbox"
            checked={state.checked}
            onChange={() => updateState({ checked: !state.checked })}
          />
    </div>
)

2:useEffect

useEffect 方法代替了 class 类组件的 componentDidMountcomponentDidUpdate,componentWillUnmount

import React, { useState, useEffect } from 'react';

function App() {
  const [ Switch, setSwitch ] = useState("打开!");
  const [ Num, setNum ] = useState(0);
  const newName = () => {
    Switch === "打开"? setSwitch("关闭"):setSwitch("打开");
  };
  const add = () => {
    setNum(Num + 1);
  };
  const minus = () => {
    setNum(Num - 1);
  };
  useEffect(() => {
    console.log("状态改变了!");
  });
  return (
    <div>
      <p>现在是:{ Switch } 状态</p>
      <button onClick={ newName }>Change Me!</button>
      <p>Num { Num }</p>
      <button onClick={ add }>加一</button>
      <button onClick={ minus }>减一</button>
    </div>
  );
}

export default App;

 

上面这个例子他会再初次渲染的时候打印 改变了状态 并且每次状态改变的时候都打印 改变了状态

那么这样的用法就是 componentDidMountcomponentDidUpdate,的使用

useEffect 第二个参数:

添加的第二个参数为监听的对象

useEffect(() => {
    console.log("状态改变了!");
  },[Num]);

当Num值发生变化时打印“状态改变了”

 

useEffect 的闭包使用:

useEffect(() => {
    console.log('装载了')
    return () => {
      console.log('卸载拉');
    };
  });

在 useEffect 中我们可以做两件事情,组件挂载完成时候,还有组件卸载时,只要在 useEffect  中使用闭包,在闭包中做我们想要在组件卸载时需要做的事就可以。

useEffect 挂载、更新、卸载同时使用:

import React, { useState, useEffect } from 'react'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'


function Index() {
    useEffect(() => {
        console.log("欢迎来到Index页面");
        return () => {
            // 解绑
            console.log("您离开了Index页面");
        }
    }, []);
    return <h2>首页</h2>
}

function List() {
    useEffect(() => {
        console.log("欢迎来到List页面");
        return () => {
            // 解绑
            console.log("您离开了List页面");
        }
    }, []);
    return <h2>列表页</h2>
}

function UseEffect() {
    const [count, setCount] = useState(0);
    useEffect(() => {
        console.log('useEffect');
        return () => {
            console.log("==========");
        }
    }, [count]);
    return (
        <div>
            <p>You clicked {count} times!</p>
            <button onClick={() => { setCount(count + 1) }}>Click me</button>
            <Router>
                <ul>
                    <li><Link to="/">首页</Link></li>
                    <li><Link to="/list">列表</Link></li>
                </ul>
                <Route path="/" exact component={Index}></Route>
                <Route path="/list" component={List}></Route>
            </Router>
        </div>
    )
}

export default UseEffect;

3:useRef 使用:

使用场景:1、设置、获取dom元素值  2、保存变量

import React,{ useState, useEffect, useRef } from 'react';

function UseRef () {
    const inputEl = useRef(null);
    const onButtonClick = () => {
        // 设置input值
        inputEl.current.value = "hello react-hooks";
        console.log('inputEl', inputEl);

    }

    const[ text,setText ] = useState("useRef");
    // 保存变量
    const textRef = useRef();

    useEffect(() => {
        textRef.current = text;
        console.log('textRef.current', textRef.current);
    });

    return (
        <>
            <input ref={inputEl} type="text" />
            <button onClick={onButtonClick}>在input上边展示文字</button>
            <br />
            <br />
            <input value={text} onChange={(e) => {setText(e.target.value)}}/>
        </>
    )
}

export default UseRef;

打印结果:3 3 3 3

import React, { useState, useEffect } from 'react';

function App() {
  const [ Num, setNum ] = useState(0);
  useEffect(() => {
      console.log(Num);
  });
  return (
    <div>
      <p>You clicked { Num } times</p>
      <button onClick={ () => { setNum(Num + 1)}}>点击三次</button>
    </div>
  );
}

export default App;

打印结果:0 1 2 3

4: useContext 使用

使用场景:如果需要在组件之间共享状态,可以使用useContext()

import React, { useState, createContext, useContext } from 'react'

const CountContext = createContext();

function Counter() {
  const count = useContext(CountContext);
  return (
    <h2>{count}</h2>
  )
}

function UseContext() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => { setCount(count + 1) }}>click me</button>
      <CountContext.Provider value={count}>
        <Counter />
      </CountContext.Provider>
    </div>
  )
}

export default UseContext;

5: useReducer 使用

useReducer 提供类似 Redux 的功能,引入 useReducer 后,useReducer 接受一个 reducer 函数作为参数,reducer 接受两个参数一个是 state 另一个是 action 。然后返回一个状态 count 和 dispath,count 是返回状态中的值,而 dispatch 是一个可以发布事件来更新 state 的。

import React, { useReducer } from 'react'

function UseReducer() {
  const [count, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case "add":
        return state + 1;
      case "sub":
        return state - 1;
      default:
        return state;
    }
  }, 0);
  return (
    <div>
      <h2>现在的分数{count}</h2>
      <button onClick={() => dispatch({ type: "add" })}>Increment</button>
      <button onClick={() => dispatch({ type: "sub" })}>Decrement</button>
    </div>
  )
}

export default UseReducer;

6: usereducer 、useContext 实现redux功能

ShowArea.js

import React, { useContext } from 'react'
import { ColorContext } from './Color'
function ShowArea() {
  const { color } = useContext(ColorContext);
  return (
    <div style={{ color: color }}>
      字体颜色为{color}
    </div>
  )
}

export default ShowArea;

Buttons.js

import React, { useContext } from 'react'
import { ColorContext, UPDATE_COLOR } from './Color'

function Buttons() {
  const { dispatch } = useContext(ColorContext);
  return (
    <div>
      <button onClick={() => { dispatch({ type: UPDATE_COLOR, color: "red" }) }}>红色</button>
      <button onClick={() => { dispatch({ type: UPDATE_COLOR, color: "yellow" }) }}>黄色</button>
    </div>
  )
}

export default Buttons;

Color.js

import React, { createContext, useReducer } from 'react';

export const ColorContext = createContext({});

export const UPDATE_COLOR = "UPDATE_COLOR";

const reducer = (state, action) => {
  switch (action.type) {
    case UPDATE_COLOR:
      return action.color;
    default:
      return state;
  }
}

export const Color = props => {
  const [color, dispatch] = useReducer(reducer, "blue");
  return (
    <ColorContext.Provider value={{ color, dispatch }}>
      {props.children}
    </ColorContext.Provider>
  )
};

Example.js
 

import React from 'react'
import ShowArea from './ShowArea'
import Buttons from './Buttons'
import { Color } from './Color'

function ReducerExample() {
  return (
    <div>
      <Color>
        <ShowArea />
        <Buttons />
      </Color>
    </div>
  )
}

export default ReducerExample;

7: useMemo 使用

未使用useMemo场景:

父组件:

function App() {
  const [name, setName] = useState('名称')
  const [content,setContent] = useState('内容')
  return (
      <>
        <button onClick={() => setName(new Date().getTime())}>name</button>
        <button onClick={() => setContent(new Date().getTime())}>content</button>
        <Button name={name}>{content}</Button>
      </>
  )
}

子组件:

function Button({ name, children }) {
  function changeName(name) {
    console.log('11')
    return name + '改变name的方法'
  }

  const otherName =  changeName(name)
  return (
      <>
        <div>{otherName}</div>
        <div>{children}</div>
      </>

  )
}

分析:

不管我们是改变name或者content的值,我们发现 changeName的方法都会被调用。
是不是意味着 我们本来只想修改content的值,但是由于name并没有发生变化,所以无需执行对应的changeName方法。但是发现他却执行了。 这是不是就意味着性能的损耗,做了无用功。

 

优化后的子组件:

function Button({ name, children }) {
  function changeName(name) {
    console.log('11')
    return name + '改变name的方法'
  }

const otherName =  useMemo(()=>changeName(name),[name])
  return (
      <>
        <div>{otherName}</div>
        <div>{children}</div>
      </>

  )
}

export default Button

总结:

这个时候我们点击 改变content值的按钮,发现changeName 并没有被调用。
但是点击改变name值按钮的时候,changeName被调用了。
所以我们可以使用useMemo方法 避免无用方法的调用

 

8: useCallback 及自定义hooks

自定义hooks useWinSize以及组件中使用useWinSize

// 自定义hooks
import React,{ useState, useEffect, useCallback } from 'react'

function useWinSize () {
    const [ size,setSize ] = useState({
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight,
    });

    const onResize = useCallback( ()=> {
        setSize({
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight,
        });
    });

    useEffect(() => {
        window.addEventListener("resize",onResize);
        return () => {
            window.removeEventListener("resize",onResize);
        }
    },[]);

    return size;
}

function UseCallback (){
    const size = useWinSize();
    return (
        <h3>页面size{size.width}*{size.height}</h3>
    )
}

export default UseCallback;






9:自定义hooks 实现获取窗口大小

/** 自定义 useWidowSize hooks */


import { useState, useEffect } from 'react';

export const useWindowSize = (props) => {
    const [ width, setWidth ] = useState('0px');
    const [ height, setHeight ] = useState('0px');

    useEffect(() => {
        setWidth(document.documentElement.clientWidth + 'px');
        setHeight(document.documentElement.clientHeight) + 'px';
    },[]);

    useEffect(() => {
        const handleResize = () => {
            setWidth(document.documentElement.clientWidth + 'px');
            setHeight(document.documentElement.clientHeight) + 'px';
        };
        window.addEventListener('resize',handleResize, false);
        return () => {
            window.removeEventListener('resize', handleResize, false);
        }
    },[])

    return [width, height];
}

/** 组件中使用自定义hooks */


import React form 'react';

const Parent = () => {
    const [ width, height ] = useWindowSize(props);

    return (
        <div>
            size:  {width} * {height}
        </div>
    )
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值