REACT Hooks

官方介绍:Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

注意事项:

  1. 只能在函数最外层调用Hook,不要再循环、条件判断或者子函数中调用
  2.  只能在React的函数组件中调用Hook,不要在其他JS函数中调用

目录

 

useState

性能优化useCallback


useState

  • 通过在函数组件中调用它来给组件添加一些内部state;
  • React会在重复渲染时保留这个state;
  • useState唯一的参数就是初始state;

useState会返回一对值,当前状态和一个让你更新它的函数,你可以在事件处理函数中或者其他地方调用这个函数,它类似class组件中的this.setState,但是它不会把新的state和旧的state进行合并。

  • 在初始渲染期间,返回的状态(state)与传入的第一个参数(initialState)值相同
  • setState函数用于更新state,它接收一个新的state值并将组件的一次重新渲染加入队列

特征:

  1. 每次渲染都是独立的闭包
  2. 每次渲染都有它自己的props and state
  3. 每次渲染都有它自己的事件处理函数
  4. alert会捕获当前触发时的状态,不会再打印更新的state (原因:每次更新state会重新render组件)
function Counter(){
    const [number,setNumber] = usestate(0);
    const alertNumber = ()=>{
        setTimeout(()=>{
            alert(number)
        },3000)
    }
    
    return (
        <>
            <p>{number}</p>
            <button onClick={()=>setNumber(number+1)}>+</button>
            <button onClick={alertNumber}>alert</button>
        </>
    )
}
ReactDOM.render(<Counter/>,document.getElementbyId('root'));

//useState是useReducer的语法糖
function useState(initalState){
    const reducer = useCallback((state,action)=>action);
    let [state,dispatch] = useReducer(reducer,initialState);
    function setState({payload}){
        dispatch({payload});
    };
    return [state,setState];
}

使用函数式更新可以解决问题

function Counter(){
    const [number,setNumber] = usestate(0);
    const alertNumber = ()=>{
        setTimeout(()=>{
            //如果这里写的函数,state就会一直以最新的状态往上加
            setNumber(number=>({number:number+1}));
            alert(number);
        },3000)
    }
    
    return (
        <>
            <p>{number}</p>
            <button onClick={()=>setNumber(number+1)}>+</button>
            <button onClick={alertNumber}>alert</button>
        </>
    )
}
ReactDOM.render(<Counter/>,document.getElementbyId('root'));

 5. 惰性初始state

  • initialState初始状态参数只会有组件初始渲染的时候调用,后续渲染会被忽略
  • 跟类组件setState不同,使用useState更新state不会自动合并,更新的时候需要传入完整的值
let [state, setState] = useSate({number:0});
//....更新state时....
setState({...state,number:number+1})

useCallback性能优化

特性:更新useState时,如果state没有变化组件不会刷新

为了减少每次刷新state的渲染次数,我们可以使用useCallback,参数:fn和deps

  • fn:执行的函数
  • deps:依赖的变量,数组格式,只有在这个变量发生变化的时候才会重新生成useCallback里传入的函数
function Counter(){
    const [number,setNumber] = usestate(0);
    const [name,setName] = usestate('tiya');
    const addNumber =  useCallback(setNumber(number+1),[name]);
    const addName =  useCallback(setName('bella'),[name]);
    return (
        <>
            <p>{number}</p>
            <p>{name}</p>
            <button onClick={addNumber}>+</button>
            <button onClick={()=>{
                addName('bella') 
            }}>alert</button>
        </>
    )
}
ReactDOM.render(<Counter/>,document.getElementbyId('root'));

useMemo性能优化

参数:fn和deps

  • fn:执行的函数,即官网(下文)说的--“创建”函数
  • deps:依赖的变量,数组格式,只有在这个变量发生变化的时候才会重新生成useMemo里传入的函数

注意:

把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。

记住,传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo

如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值。

依赖项数组不会作为参数传给“创建”函数。未来也许有可能

// 案例
import React,{useState,useCallback,memo,useMemo} from 'react';
import ReactDOM from 'react-dom';

function Child(props){
  console.log('render Child');
  return (
    <button onClick={props.addClick}>{props.data.number}</button>
  )
}
Child = memo(Child);
function App() {
  let [number,setNumber]=useState(0);
  let [name,setName] = useState('tiya');
  const addClick = useCallback(()=>setNumber(x=>x+1),[]);
  //const addClick = useCallback(()=>setNumber(number+1),[number]);
  const data = useMemo(()=>({number}),[number]);
  
  return (
    <div>
      <input type="text" value={name} onChange={e=>setName(e.target.value)}/>
      <Child addClick={addClick} data={data}/>
    </div>
  );
}
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

useReducer

function reducer(state,action){
    switch(action.type){
        case 'Add':
            return {number:state.number+1};
        case 'Minus':
            return {number:state.number-1};
        default:
        return state;
    }
}
const App = ()=>{
   let [state,dispatch] = useReducer(reducer,initalState);
    return (
        <div>
            <p>{state.number}</p>
           <button onClick={()=>dispacth({type:'Add'})}>+</button>
            <button onClick={()=>dispacth({type:'Minus'})}>-</button>
        </div>
    ) 
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值