zoukankan      html  css  js  c++  java
  • react basic concept

    This artical will display the concept of react

    ReactNode vs ReactElement

    let's see the code definition. ReactNode is a superset of ReactElement, ReactElement is an object with type, props, key

    interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
            type: T;
            props: P;
            key: Key | null;
        }
    
    
    type ReactText = string | number;
    type ReactChild = ReactElement | ReactText;
    
    interface ReactNodeArray extends Array<ReactNode> {}
    type ReactFragment = {} | ReactNodeArray;
    type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
    

    Order when React updating the virtual Dom.

    See the code Sample bellow. Assume current State is 1, and we Click button, state will be setted to 2, then in RenderDemo, it will first update 2 to InnerInner, but function is not executing, then executing Inner, InnerInner by order.
    After also checking the class componnet, I found order is, in render function, first it will assign values to every component(either class or function), then it will execute render in each component iterate, one by one. Before any component'render function executing or any lifecycle methods executed, all properties and children has already been updated in parent component so the order in bellow example is innerFunction, innerFunction, innercomponnet, innerInnerComponnet

    const Inner:React.FC=({children})=>{
        return (
            <div>{children}</div>
        );
    }
    
    const InnerInner=React.forwardRef<HTMLDivElement,any>(({children},ref)=>{
        return (
            <>
            <div ref={ref}>{children}</div>
            </>
        );
    });
    
    interface PropsType{
        value:number;
        children?:any;
    }
    class InnerComponnet extends React.Component<PropsType>{
    
        static getDerivedStateFromProps(props:PropsType,state:any){
            console.log(`InnerComponent is ${props.value}`);
            const childValue = props.children.props.value;
            console.log(`in InnerComponent, the child props is ${childValue}`)
        }
    
        constructor(props:PropsType){
            super(props);
            this.state={};
        }
    
        render(){
            console.log(`render in InnerComponnet`);
            return (
                <div>{this.props.children}</div>
            )
        }
    }
    
    class InnerInnerComponnet extends React.Component<PropsType>{
        constructor(props:PropsType){
            super(props);
            this.state={};
        }
    
        static getDerivedStateFromProps(props:PropsType,state:any){
            console.log(`InnerInnerComponent is ${props.value}`);
        }
    
        render(){
            console.log(`render in InnerInnerComponnet`);
            return (
                <div>{this.props.value}</div>
            )
        }
    }
    
    const RenderDemo:React.FC = ()=>{
        const [state,setState]=React.useState<number>(0);
        return(
            <>
                <div className="each-example">
                    <h2>Render Order Demo</h2>
                    <Button onClick={()=>{setState(pre=>pre+1);console.log(`pre is ${state}`);}}>Click to increase</Button>
                    <Inner>
                        <InnerInner>{state}</InnerInner>
                    </Inner>
    
                    <h2>This is class Componnet</h2>
                    <InnerComponnet value={state}>
                        <InnerInnerComponnet value={state}/>
                    </InnerComponnet>
                </div>
            </>
        );
    }
    

    下面列出几个问题,然后慢慢给出解答

    • FC 如果当普通函数用,同时 FC 里面有 useRef/useMemo 等 hook 函数,那么 hook 函数还能正常工作吗?
      答案是如果 FC 当作普通函数用,那么 FC 跟 hook 函数是一样的行为,它里面的 useRef/useMemo 等数据存储在调用 FC 的组件内部。很有意思。还有,React 指出 hook api(原生的 API) 函数必须要在最顶层(这其实是一个静态的语法检查),不能置于任何条件以及块语句内部,实际上,我们可以使用自定义的 hook 函数绕过去,我们只要保证函数运行过程中 hook 函数的数量保持不变就行了。下面来个简单的例子
    const FCC1: React.FC<{ content: string; count: number; isOverride?: boolean }> =
      ({ content, count, isOverride }) => {
        const text = React.useRef<string>(content);
        if (isOverride) {
          text.current = content;
        }
        return <span>{`Conent is ${text.current} and count is ${count}`}</span>;
      };
    const FCC2 = ({
      content,
      count,
      isOverride,
    }: demoState & { isOverride?: boolean }) => {
      const text = React.useRef<string>(content);
      if (isOverride) {
        text.current = content;
      }
      return text.current;
    };
    
    const FCDemo: React.FC = () => {
      const [state, setState] = React.useState<demoState>({
        content: "a",
        count: 0,
      });
      const onincrease = () => {
        setState((pre) => ({ content: `${pre.content}a`, count: pre.count + 1 }));
      };
      const { content, count } = state;
      let fccResult;
      if (count % 2 === 0) {
        fccResult = FCC1(state);
      } else {
        const test = FCC2({ ...state, isOverride: true });
        fccResult = (
          <span>{`I am from local content is ${test} count is ${count}`}</span>
        );
      }
      return (
        <>
          <button type="button" onClick={onincrease}>
            Click ToChange
          </button>
          <h3>
            content update when count is
            even,下面其实是两个不同的FC,它们共享了同一个槽位,所以React没有报错,证明就是变化是a,aa,aa,aaaa,aaaa,aaaaaa,如果是不同槽位,应该是a,aa,a,aaaa,a,aaaaaa
          </h3>
          {fccResult}
        </>
      );
    };
    
    • 研究一下 hook 函数的源码,了解它的实现原理 useMemo, useRef,这两个简单点先来。
  • 相关阅读:
    [iOS UI进阶
    [iOS UI进阶
    [iOS基础控件
    [iOS基础控件
    [iOS基础控件
    [iOS基础控件
    为什么会使用内部临时表
    Django日志模块配置
    mysql join语句分析(一)
    mysql误删数据以及kill语句工作原理
  • 原文地址:https://www.cnblogs.com/kongshu-612/p/14841616.html
Copyright © 2011-2022 走看看