从父组件更改React挂钩状态

Had*_*bar 7 reactjs react-hooks

我有一个像这样的钩子组件:

import React, { useState} from "react";

    const MyComponent = props => {
      const [value, setValue] = useState(0);
      const cleanValue = () => {
        setValue(0);
      };

      return (<span><button onClick={()=>setValue(1)}/>{value}<span>)
    }
Run Code Online (Sandbox Code Playgroud)

我想重置父组件的值。如何调用父组件的纯净值?父组件是有状态组件。

Apr*_*ion 10

从 React 文档中关于完全不受控制的组件与键

为了重置值...,我们可以使用名为key. 当 akey发生变化时,React 将创建一个新的组件实例而不是更新当前的组件实例。键通常用于动态列表,但在这里也很有用。

在这种情况下,我们可以使用一个简单的计数器来指示MyComponent按下Reset按钮后是否需要一个新实例:

const { useState } = React;

const Parent = () => {
  const [instanceKey, setInstanceKey] = useState(0)
  const handleReset = () => setInstanceKey(i => i + 1)
  return (
   <div>
    <MyComponent key={instanceKey} />
    <button onClick={handleReset} type="button">Reset</button>
   </div>
  )
}

const MyComponent = () => {
  const [value, setValue] = useState(0)
  return (
    <span>
      <button type="button" onClick={()=>setValue(v => v + 1)}>{value}</button>
    </span>
  )
};

ReactDOM.render(<Parent />, document.getElementById('app'));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app"/>
Run Code Online (Sandbox Code Playgroud)


Shu*_*tri 9

如果父级必须控制子级状态,则该状态可能必须驻留在父级组件本身中。但是,您仍然可以使用ref从父级更新子状态,并在子级中公开一个reset方法。您可以利用useImperativeHandle钩子使子项仅向父项公开特定属性

const { useState, forwardRef, useRef, useImperativeHandle} = React;


const Parent = () => {
  const ref = useRef(null);
  return (
     <div>
      <MyComponent ref={ref} />
      <button onClick={() => {ref.current.cleanValue()}} type="button">Reset</button>
     </div>
  )
}

const MyComponent = forwardRef((props, ref) => {
  const [value, setValue] = useState(0);
  
   const cleanValue = () => {
    setValue(0);
  };

  useImperativeHandle(ref, () => {
     return {
      cleanValue: cleanValue
     }
  });

  return (<span><button type="button" onClick={()=>setValue(1)}>Increment</button>{value}</span>)
});
ReactDOM.render(<Parent />, document.getElementById('app'));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app"/>
Run Code Online (Sandbox Code Playgroud)


Mat*_*eer 5

You can't / shouldn't. Using hooks instead of stateful class components doesn't change the fact that if you want the parent to own the state, you need to declare the state in the parent.

It should look something like this, depending on when you want to reset the value (here I used another button):

const MyButton = (props) = (
  // Whatever your button does, e.g. styling
  <span>
    <button {...props} />
  <span>
)


const Parent = props => {
  const [value, setValue] = useState(0);
  const cleanValue = () => setValue(0);
  return (
    <div>
      <MyButton onClick={() => setValue(1)}>
        {value}
      </MyButton>
      <button onClick={cleanValue}>
        Reset
      </button>
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)