Skip to content

useRef

脱围机制,通过.current访问

  • 数据脱围
  • DOM
  • 操作组件,19之前需要配合forwardRef包裹子组件,19后就不需要了,并且把第一个参数props合并到了参数ref

useImperativeHandler

对父组件传过来的ref进行属性和操作的可控暴露,感觉有点像defineExpose的功能

tsx
import React, { useRef, forwardRef, useImperativeHandle } from 'react';

// 使用forwardRef转发ref到子组件
const FancyInput = forwardRef((props, ref) => {
  // 创建组件内部的ref
  const inputRef = useRef();
  
  // 自定义暴露给父组件的ref方法
  useImperativeHandle(ref, () => ({
    // 只暴露focus方法给父组件
    focus: () => {
      inputRef.current.focus();
    }
  }));
  
  return <input ref={inputRef} />;
});

function App() {
  // 创建引用FancyInput组件的ref
  const inputRef = useRef();
  
  return (
    <div>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>
        Focus the input
      </button>
    </div>
  );
}

export default App;

useContext

相比直接全局变量来说,可以控制注入范围

创建:

tsx
const myContext = React.createContext({}: type)

在注入范围上使用,19后可以不需要加.Provider

tsx
<MyContext.Provider value={{/*type型的值*/}}>
</MyContext.Provider>

注意,如果value传入的对象更改,那么对应的所有引用context的组件也会重新渲染。

可以想到,如果你传入了一个局部函数,或者局部对象,那么每次挂载含有Provider的组件时,也会使得含Context的组件重渲染,所以在重要的地方可以缓存

tsx
function Parent(){
  const callback = useCallback(()=>{},[])
  const value = useMemo(()=>{
    return {fn: callback}
  }, [callback])
  return <MyContext.Provider value={value}>
            <Children />
        </MyContext.Provider>
}

子组件使用

tsx
const context = useContext(myContext)