React面试题


React面试题
什么是 jsx
jsx ( javascript xml ) , 是javascript 语法的扩展,

jsx    是React.createElement 的语法糖。

jsx优点: 
   
  体现了React申明式的优点,
  
  
什么是 React 副作用
就是除了状态相关的逻辑,比如网络请求,监听事件,查找 dom。

在react中,有些副作用需要清除,有些副作用无需清除。

比如手动变更dom, 记录日志这些都无需清除。

而订阅外部数据源、添加定时器等容易造成内存泄露,就很有必要清除。

    例如: 组件已经卸载了,但定时器还没有关闭,那么就会报错!!
    
    
// 在组件卸载时,取消订阅外部数据源
    
// axios 官方支持的 中断请求方法
useEffect(() => {
  const source = axios.CancelToken.source();
  const fetchData = async () => {
    try {
      const response = await Axios.get("/companies", {
        cancelToken: source.token
      });
      // ...
    } catch (error) {
      if (Axios.isCancel(error)) {
        //cancelled
      } else {
        throw error;
      }
    }
  };
  fetchData()
  return () => {
    source.cancel();
  };
}, [companies]);

参看资料: 

https://www.jianshu.com/p/e1ff909aca88  // 简书

https://www.jianshu.com/p/fdab5a6fa1aa
纯函数
概念:

1. 一个函数,它的计算不依赖外部的变量,它就是纯函数。

2. 一个函数在执行过程中发生了外部可变的变化,就不是纯函数,反之则是。

    一般来讲就是发生了和运算返回值无关的事,就不是纯函数例如:
    
    修改外部作用域 / 全局变量;
    
    修改传入的参数,发送请求、console.log 、操作dom都属于副作用。
    
    
useEffect 和useLayoutEffect 的区别
useLayoutEffect:是在所有DOM变更之后浏览器渲染之前调用,既同步调用

useEffect:是在组件渲染到屏幕之后执行,既异步调用

useLayoutEffect 相比 useEffect,通过同步执行状态更新可解决一些特性场景下的页面闪烁问题。

useEffect 可以满足百分之99的场景,而且 useLayoutEffect 会阻塞渲染,请谨慎使用
什么是useRef

返回的 ref 对象在组件的整个生命周期内保持不变

当更新 current 值时并不会 re-render ,这是与 useState 不同的地方

采用useRef,作为组件实例的变量,保证获取到的数据肯定是最新的。


三、useRef与createRef的区别

在一个组件的正常的生命周期中可以大致分为3个阶段:

从创建组件到挂载到DOM阶段。初始化props以及state, 根据state与props来构建DOM

组件依赖的props以及state状态发生变更,触发更新

销毁阶段

第一个阶段,useRef与createRef没有差别

第二个阶段,createRef每次都会返回个新的引用; 而useRef不会随着组件的更新而重新创建

第三个阶段,两者都会销毁

// 总结
useRef可以用来定义变量,这些变量更改之后不会引起页面重新渲染。

useRef也可以用来区分初始渲染还是更新(通过current有没值,具体见示例库里的didOrUpdate.tsx)

在DOM节点上定义ref属性,通过.current就可以获取到该DOM元素

通过forwardRef就可以给函数子组件传入ref属性。

使用useImperativeHandle用于定义暴露给父组件的ref方法
useEffect使用异步函数
useEffect 不能直接使用async await 语法糖.

/* 错误用法 ,effect不支持直接 async await*/
 useEffect(async ()=>{
        /* 请求数据 */
      const res = await getData()
 },[]);

useEffect 的回调参数返回的是一个清除副作用的 clean-up 函数。

因此无法返回 Promise,更无法使用 async/await

// 那么如何让useEffect 支持 async await ?

1. 
   
useEffect(() => {
    (async function getDatas() {
      await getData();
    })();
  }, []);
  return <div></div>;
};

2. 

 useEffect(() => {
    const getDatas = async () => {
      const data = await getData();
      setData(data);
    };
    getDatas();
  }, []);
自定义hook & 高阶组件
自定义hook :

    将一些常用的,跨越多个组件的hook逻辑代码抽离出去就是一个自定义hook。

    自定义 hook 内部仍使用hook, 因此其内部同样也要遵循hook规则。

    每个组件间的 state 是完全独立的。
    
    Hook 是一种复用 状态逻辑  的方式,它不复用 state 本身。
    
    事实上 Hook 的每次调用  都有一个完全独立的state —— 
    
    因此你可以在单个组件中多次调用同一个自定义 Hook。 // ??? 为什么是独立的state

 规则: 
 
    1. 函数名以use开头
    
    2.     其他组件调用自定义hook, 也应该放到最顶层。


// 自定义 hook vs 高阶组件
 
高阶组件同样可以封装重复的逻辑代码,达到代码复用,减少冗余代码的作用。

但是:

    1. 高阶组件 没有 自定义hook来的优雅,

    2. 高阶组件也会导致组件嵌套层次过深。

文章作者: KarlFranz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 reprint policy. If reproduced, please indicate source KarlFranz !
评论
  目录