美文网首页
useRef、useImperativeHandle、useCa

useRef、useImperativeHandle、useCa

作者: 吴占超 | 来源:发表于2021-07-01 11:24 被阅读0次

react hook
父组件调用子组件
父子:

官方文档

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

在本例中,渲染 <FancyInput ref={inputRef} /> 的父组件可以调用 inputRef.current.focus()

个人实例:

useRef 版本(不更新state页面不会渲染更新)

import { Maybe } from 'graphql/jsutils/Maybe';
import {
  FC,
  forwardRef,
  ForwardRefRenderFunction,
  RefObject,
  useImperativeHandle,
  useRef,
} from 'react';
import { useImmer } from 'use-immer';

// #region ChildA
interface IChildAProp {
  /**
   * 可空值
   */
  inValue?: Maybe<string> | undefined;
}

interface IChildARef {
  inputValue: Maybe<string> | undefined;
}

const ChildA: ForwardRefRenderFunction<IChildARef, IChildAProp> = (
  props,
  cref
) => {
  const [textValue, setTextValue] = useImmer(props.inValue || '我是默认值');

  const handleChange = (event: any) => {
    setTextValue((draft) => event.target.value);
  };

  useImperativeHandle(
    cref,
    () => ({
      inputValue: textValue,
    }),
    [textValue]
  );
  return (
    <input
      type="text"
      name="textA"
      id="textA"
      value={textValue}
      onChange={handleChange}
    />
  );
};

const ChildAComponents = forwardRef(ChildA);
// #endregion

const ParentA: FC = () => {
  const refChildA = useRef<IChildARef>() as RefObject<IChildARef>;
  return (
    <>
      <ChildAComponents inValue={'默认值'} ref={refChildA} />
      {refChildA.current?.inputValue}
    </>
  );
};

export default ParentA;

image.png
看起来很美好,但是有什么不对~~嗯state没有更新。
如何这时候想到的是 useEffect 呢么就是错的~
划重点 useCallback 闪亮登场!

useCallback版本(更新state页面渲染更新)

import { Maybe } from 'graphql/jsutils/Maybe';
import {
  FC,
  forwardRef,
  ForwardRefRenderFunction,
  RefObject,
  useCallback,
  useImperativeHandle,
  useRef,
} from 'react';
import { useImmer } from 'use-immer';

// #region ChildA
interface IChildAProp {
  /**
   * 可空值
   */
  inValue?: Maybe<string> | undefined;
}

interface IChildARef {
  inputValue: Maybe<string> | undefined;
}

const ChildA: ForwardRefRenderFunction<IChildARef, IChildAProp> = (
  props,
  cref
) => {
  const [textValue, setTextValue] = useImmer(props.inValue || '我是默认值');

  const handleChange = (event: any) => {
    setTextValue((draft) => event.target.value);
  };

  useImperativeHandle(
    cref,
    () => ({
      inputValue: textValue,
    }),
    [textValue]
  );
  return (
    <input
      type="text"
      name="textA"
      id="textA"
      value={textValue}
      onChange={handleChange}
    />
  );
};

const ChildAComponents = forwardRef(ChildA);
// #endregion

const ParentA: FC = () => {
  // const refChildA = useRef<IChildARef>() as RefObject<IChildARef>;
  const [displayTxt, setDisplayTxt] = useImmer<string | undefined>(undefined);

  const refChildA = useCallback(
    (current: IChildARef) => {
      setDisplayTxt((draft) => current && current.inputValue?.toString());
    },
    [setDisplayTxt]
  );

  return (
    <>
      <ChildAComponents inValue={'默认值'} ref={refChildA} />
      {/* {refChildA.current?.inputValue} */}
      {displayTxt}
    </>
  );
};

export default ParentA;

image.png

相关文章

网友评论

      本文标题:useRef、useImperativeHandle、useCa

      本文链接:https://www.haomeiwen.com/subject/ethjultx.html