React最佳实践

504 阅读3分钟

想必大家刚接触React的时候写法都是这样的

第一版(初识React)

const index = () => {
  const [number, setNumber] = useState(1);
  const updateNumber = () => {
    setNumber(number + 1);
  };
  return (
    <>
      <div>
        number:{number}
        <Button
          type="primary"
          onClick={() => {
            updateNumber();
          }}>
          新增
        </Button>
      </div>
     
    </>
  );
};

可是随着时间需求迭代,代码量的增加发现代码越来越不好维护,那就有了后续的分功能模块组件写,大概就是这样

第二版(组件结构化)

const Header = () => {
  return (
    <>
      我是Header
    </>
  );
};
const Footer = () => {
  return (
    <>
      我是Footer
    </>
  );
};

const Index=()=>{
   return <>
    <Header/>
    <Footer/>
   </>
}

这么写看起来好像没有问题,但是一旦代入数据流,比如我们自定义一个弹窗,可是我们开启弹窗的按钮又在父组件中,相当于父组件要调用子组件的方法,这时我们就要这样写了

第三版(熟练之路)

const CustomModal =forwardRef((props,parentRef) => {
    const [open,setOpen]=useState(false)
    
    const handleOpen=()=>{
        setOpen(true)
    }
    
  useImperativeHandle(parentRef, () => ({
    handleOpen,
  }));
  return (
    <Modal>
      我是Header
    <Modal/>
  );
});
const Footer = () => {
  return (
    <>
      我是Footer
    </>
  );
};

const Index=()=>{
    const modalRef = useRef(null)
    
    const handleOpenModal=()=>{
        modalRef.current?.handleOpen()
    }
    
   return <>
        <Button >查看</Button>
        <CustomModal ref={modalRef} />
        <Footer/>
       </>
}

是不是很啰嗦,对于一个经常开发中后台的我,简直是糟糕透了!

u=529178402,2777994954&fm=253&fmt=auto&app=138&f=JPEG.webp

为了解决当前问题,就出现了第四版的写法,复杂的功能逻辑UI容器抽离,UI容器的所有内容都通过props传递,对于UI容器的逻辑全部抽离为hooks,这样其实所有的方法,任意调用和传递,代码如下

第四版(开始创新)

大概就是这个样子,但是随之而来的又一个问题是,父组件的更新会导致所有子组件render,大家点击新增Add发现 Footer组件打印了render,这时候我相信大家就一定会想到用memo,同样小编也是这么想的,然而并没有什么用

因为memo只是浅比较,每次render其实都是会生成新的footer变量,那这其实在大模块下是极其耗费性能的,那该怎么办呢?由此就引发我开发新的功能组件Action,代码如下

import React, { Fragment } from 'react';
export interface ActionProps<T extends Record<string, any>, K> {
  children: (params: T) => React.ReactNode;
  useHooks: (options?: K) => T;
  options?: K;
}
const Action = <T extends Record<string, any>, K>({ children, useHooks, options }: ActionProps<T, K>) => {
  const data = useHooks(options);
  return <Fragment>{children(data)}</Fragment>;
};
export default Action;

首先我们要明白一个道理React需要更新UI时,它会重新渲染整个组件树,并通过diffing算法(即虚拟DOMdiff算法)来找出需要更新的地方,整个组件树,其实只是你的父级。换句话来说,如果我们只想让Header渲染,其实只需要给Header加一个父级组件即可,代码如下

第五版(渐行渐远)

这时候大家在点击新增AddFooter组件就没有任何打印了,我觉得在开发中,只有公共使用的放在最上层,其他的相关hooks只应该放在当前组件的父级。即使后期调整,也会很容易发现受影响的地方。

总结

大家有没有发现整个过程,其实就像一个前端的的成长历程,为什么有的人干了3年和干了1年的差不多,对于这个问题刚开始我也很疑惑🤔。但后来我理解了,就像我的第一版第五版的过程,你可以选择折腾,也可以选择安逸,毕竟用第一版也能开发,老板也不会关心你代码好赖,后期是否好维护也未必和你有关...嗯,突然想到了网上最近很流行的一段话,你本来就是打工的,只是恰巧上了几年学而已😄😄😄

最后

到此我的的React最佳实践就结束了,欢迎大家点评、如果觉得不错可以点赞➕收藏哟😌