useRef、useImperativeHandle、useCa
2021-07-01 本文已影响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;

看起来很美好,但是有什么不对~~嗯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;
