react hooks学习总结

react hooks学习总结

react hooks优点

1:解决了class组件状态逻辑难以复用的问题
2:解决了class组件复杂难以维护的问题
生命周期函数中包含了很多不相干的逻辑,比如componentDidUpdate中只要一个字段发生变化都会触发,为了优化这种场景会写很多的优化逻辑;
类组件中到处都是对状态的访问和处理,导致组件难以拆分成更小的组件;
3:解决了类组件中this的问题
4:解决了函数组件中不能有自己状态的问题

常用的hooks

useState,
const [status, setStatus] = useState(initState);
当使用多个useState的时候必须保证每次他们的调用顺序是一样的;
initState可以是一个函数,用来处理initState需要经过复杂计算得到;

useEffect,
useEffect(() => {
return () => {};
}, [a, b]);
第一个参数相当于class组件的componentDidMount和componentDidUpdate,return值相当于componentWillUnmount,第二个参数是一个数组,表示依赖项,只有依赖项发生改变时,第一个函数参数才会执行;
每次组件重新运行effect都会清除上一个effect,组件卸载的时候也会执行清除副作用的函数;
当第二个参数不传递时,每次组件重新渲染都会重新运行effect(默认是依赖所有);
useEffect会在dom更新完成后才会执行;
useEffect的返回值要么是一个函数要么什么都不返回,不能是async函数,他的返回值是一个promise;

useLayoutEffect,
useLayoutEffect和useEffect函数签名一致,区别是所有的effect会在组件渲染之后浏览器绘制之前同步执行;

useReducer,
const [state, dispatch] = useReducer(reducer, initialArg, init);
reducer类似于redux中的reducer,

const reducer = (state, action) {
     
  switch (action.type) {
     
    case 'increment':
      return {
     count: state.count + 1};
  }
}

initialArg用来初始化state;
如果设置了第三个参数init函数,那么state的初始值会被设置为init(initArg)
dipatch是一个引用类型,会一直保持不变;
useReducer中每次取到的state都是最新的值;

useMemo,
const f2 = useMemo(() => {}, [a, b])
只要a和b的值保持不变,f2的值一直保持不变,一直是第一个入参函数的调用值,第一个入参函数一直不会执行;

useCallback,
const f1 = useCallBack(() => {}, [a, b]);
只要依赖项a和b保持不变,函数f1一直保持不变,也即是f1一直是第一个入参函数
一般用来缓存一些计算量比较大的运算,节省内存

useContext,
接收context对象(React.creatContext({})创建的对象),并返回该对象的当前值;
useContext用来获取context的值并且订阅context的变化;
使用示例

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}>
     <ThemedButton />
   </ThemeContext.Provider>
 );
}
function ThemedButton() {
     
 const theme = useContext(ThemeContext);
 return (
   <button style={
     {
      background: theme.background, color: theme.foreground }}>
     I am styled by theme context!
   </button>
 );
}

useRef
const refContainer = useRef(initialValue);
refContainer保存的是一个可变的值, 在整个组件的生命周期内保持不变,是一个引用类型;
initialValue是refContainer.current初始值;
通过改变refContainer.current的值来解决一些react hooks开发过程中遇到的闭包问题;

useRef+forwardRef+useImperativeHandle
const = useImperativeHandle(ref, createHandle, [deps]);
通过useRef+forwardRef+useImperativeHandle来控制暴露给父组件的ref值;

function Child(props, ref) {
     
 const inputRef = useRef();
 useImperativeHandle(ref, () => ({
     
   focus: () => {
     
     inputRef.current.focus();
   }
 }));
 return <input ref={
     inputRef} />;
}
Child = forwardRef(Child);
function Parent() {
     
 const parentRef = useRef();
 const handleClick = () => {
     
   parentRef.current.focus();
 }
 return (
   <div>
     <Child  ref={
     parentRef}/>
     <Button onClick={
     handleClick}>点我</Button>
   </div>
 );
}

//下面两个hooks是react-redux中提供的hooks

useSelector

import {
     useSelector} from 'react-redux';
const state = useSelector(state => state.someState)

useDispatch

import {
     useDispatch} from 'react-redux';
const dispatch = useDispatch();

自定义hook:
以use开头并且使用了其他hook

hooks使用注意事项

hooks只能在react 函数组件中以及自定义hooks中使用, 不能用在js普通函数以及类组件中;
hooks只能用在函数顶部,保证每次组件渲染时hooks的执行顺序是一样的,不能用在条件语句,循环语句以及嵌套函数中;

hooks原理简介

todo:

eslint规则校验

npm install eslint-plugin-react-hooks --save-dev
// 你的 ESLint 配置

{
     
 "plugins": [
   // ...
   "react-hooks"
 ],
 "rules": {
     
   // ...
   "react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
   "react-hooks/exhaustive-deps": "warn" // 检查 effect 的依赖
 }
}

高阶组件Hoc,renderProps和hooks的区别?

Hoc:一个纯函数,接收一个组件并返回另一个组件;redux的connect就是通过高阶组件实现的;

withMouse(withPage(MyComponent))

缺点:组件参数容易被串改(组件本身容易被改写,组件参数统一高阶组件覆盖);包装组件参数不知道数据来源比较难调试;

const MyComponent = () => {
  return (
    
      {({ x, y }) => (
        
          {({ x: pageX, y: pageY }) => (
            
              {({ api }) => {
                // yikes
              }}
            
          )}
        
      )}
    
  )

renderProps: 该组件通过属性函数(render或者children)返回一个react元素实现自己的渲染逻辑;react-router是通过renderProps实现的;
缺点:容易造成嵌套地狱;

<Mouse>
 {
     
   (position) => {
     
     return <Cat position={
     position} />
   }
 }
</Mouse>
class Mouse extends React.PureComponent {
     
 ...逻辑
 return (
   this.props.children(data)
 )
}

参考文章

https://overreacted.io/zh-hans/making-setinterval-declarative-with-react-hooks
https://juejin.im/post/5dbbdbd5f265da4d4b5fe57d#heading-30

你可能感兴趣的:(react,react)