React 状态不断重置为初始状态

时间:2021-07-26 04:48:59

标签: reactjs react-hooks material-ui formik-material-ui react-forwardref

我目前正在我的网站上开发移动签名功能。我正在处理三个组件:Form.js(父级,使用 Formik 作为表单)、Admin.js(Form 的子级)和 Signature.js(Admin 的子级)。

当您以纵向模式到达此页面(表单的管理部分)时,它会呈现一条消息,要求您将手机横向进行签名。当您转向横向时,会弹出一个按钮:“单击此处签名”。当您单击它时,会弹出一个带有签名画布(react-signature-canvas)的全屏 material-ui 对话框。您签名,然后单击“保存并关闭”关闭全屏对话框,然后单击“保存签名”将签名保存到您的个人资料中。

使用断点,我发现当您单击对话框中的“保存并关闭”将其关闭时,状态会与签名一起正确保存。但是当您在表单的“管理”部分单击“保存签名”时,状态已重置为其初始状态 null。

我相信解决方案是使用 forwardRef 钩子,但问题是我看到的大多数示例都是将 ref 从一个组件转发到另一个组件,我认为我需要让它像我的组件一样通过一个附加组件是结构化的(从签名 --> 传递到管理员 --> 到表单)。 我需要从 Signature.js 到 Form.js 获取 SignatureCanvas (react-signature-canvas) 的引用。以下是每个文件的相关信息:

Signature.js

const Signature = forwardRef((props, ref) => {
    return (
        <SignatureCanvas
           backgroundColor="transparent"
           canvasProps={{
              width: mobileWidth,
              height: mobileHeight - 60,
              className: 'sigCanvas',
           }}
           penColor="black"
           ref={ref}
         />
     );
};

Admin.js

const Admin = () => {
    const { values } = useFormikContext();
    const signatureRef = useRef(null);

    return (
       <Signature values={values} ref={signatureRef} />
    );
 };

Form.js

const Form = () => {
    const { values } = useFormikContext();
    const signatureRef = useRef(null);

    return (
       <Admin ref={signatureRef} />
    );
 };

我研究并认为我可能需要使用 useCallback 钩子而不是转发 ref 或根本使用 refs,但我不确定如何实施,如果这是正确的解决方案。我还尝试在 Form 组件中设置状态并将其传递给 Admin 然后传递给 Signature 但没有任何运气。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

我不确定这是否能解决您的问题,但您可以通过多次使用 refforwardRef 传递给多个组件。

我创建了一个示例来展示这一点,您可以在 enter image description here 上查看。

const DeeplyNestedComponent = forwardRef((_, ref) => <input ref={ref} />);

const NestedComponent = forwardRef((_, ref) => (
  <DeeplyNestedComponent ref={ref} />
));

const BaseComponent = () => {
  const [inputValue, setInputValue] = useState('');
  const ref = useRef();

  return (
    <>
      <p>Last input value: "{inputValue}"</p>
      <NestedComponent ref={ref} />
      <button onClick={() => setInputValue(ref.current.value)}>
        Read input
      </button>
    </>
  );
};