【问题标题】:Is there a generic way to set state in React Hooks? How to manage multiple states?在 React Hooks 中设置状态是否有通用方法?如何管理多个状态?
【发布时间】:2019-11-18 21:22:32
【问题描述】:

我有一个问题,我是否可以在 React Hooks 中使用 useState generic,就像我可以在 React Components 中同时管理多个状态一样?

state = {
  input1: "",
  input2: "",
  input3: ""
  // .. more states
};

handleChange = (event) => {
  const { name, value } = event.target;
  this.setState({
    [name]: value,
  });
};

【问题讨论】:

  • 你的意思是用状态变量做这个吗?如果您使用更复杂的状态,那么显然这可以类似于在您的类组件示例中完成的方式。对于前者,请参阅我的answer,它演示了动态设置变量状态的能力。
  • @ravibagul91 不一定,你可以用useState管理复杂的状态
  • @James 是的,这就是我要找的。我将深入研究您的链接答案

标签: javascript reactjs react-hooks


【解决方案1】:

是的,使用钩子,您可以通过三种方式管理复杂的状态(无需 3rd 方库),其中主要的原因是管理 状态 ID 及其相应的元素。

  1. 管理具有多种状态的单个对象(注意数组就是对象)。
  2. 如果 (1) 太复杂,请使用 useReducer
  3. 为每个键值对使用多个useState(考虑它的可读性和维护性)。

看看这个:

// Ids-values pairs.
const complexStateInitial = {
  input1: "",
  input2: "",
  input3: ""
  // .. more states
};

function reducer(state, action) {
  return { ...state, [action.type]: action.value };
}

export default function App() {
  const [fromUseState, setState] = useState(complexStateInitial);

  // handle generic state from useState
  const onChangeUseState = (e) => {
    const { name, value } = e.target;
    setState((prevState) => ({ ...prevState, [name]: value }));
  };

  const [fromReducer, dispatch] = useReducer(reducer, complexStateInitial);

  // handle generic state from useReducer
  const onChangeUseReducer = (e) => {
    const { name, value } = e.target;
    dispatch({ type: name, value });
  };
 
  return (
    <>
      <h3>useState</h3>
      <div>
        {Object.entries(fromUseState).map(([key, value]) => (
          <input
            key={key}
            name={key}
            value={value}
            onChange={onChangeUseState}
          />
        ))}
        <pre>{JSON.stringify(fromUseState, null, 2)}</pre>
      </div>

      <h3>useReducer</h3>
      <div>
        {Object.entries(fromReducer).map(([key, value]) => (
          <input
            name={key}
            key={key}
            value={value}
            onChange={onChangeUseReducer}
          />
        ))}
        <pre>{JSON.stringify(fromReducer, null, 2)}</pre>
      </div>
    </>
  );
}

备注

  • 与类组件中的setState 方法不同,useState 不会自动合并更新对象。您可以通过将函数更新程序形式与对象传播语法相结合来复制此行为:
setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

请参阅React Docs

【讨论】:

  • 这不使用反应钩子。
  • 这是正确的,但不是使用反应钩子的方法。
  • setState 来自useState: const [state, setState] = useState(initialState);
  • @DennisVash:我很抱歉。你是对的。我没有看到您的 setState 声明,并认为它与 OP 似乎要询问的类 setState 方法相同。我的困惑是您使用了相同的方法名称。
  • @James:不要自以为是。我想我们实际上是同意的。您的自定义钩子答案最终可能是 OP 正在寻找的答案。
【解决方案2】:

我实际上并没有对此进行测试,但它应该可以工作。

请参阅https://reactjs.org/docs/hooks-reference.html#usestate 了解更多信息。

import React, {useState} from 'react';

const MyComponent = () => {
    const [name, setName] = useState('Default value for name');
    return (<div><button onClick={()=>setName('John Doe')}}>Set Name</button></div>);
};
export default MyComponent;

【讨论】:

  • 我不明白这是如何回答这个问题的?您刚刚给出了如何使用setState 的示例,OP 如何从中推断出如何动态设置它?
【解决方案3】:

做你想做的事情的正确方法是创建你自己的在内部使用useState的钩子。

这是一个例子:

// This is your generic reusable hook.
const useHandleChange = (initial) => {
  const [value, setValue] = React.useState(initial);
  const handleChange = React.useCallback(
    (event) => setValue(event.target.value), // This is the meaty part.
    []
  );
  return [value, handleChange];
}

const App = () => {
  // Here we use the hook 3 times to show it's reusable.
  const [value1, handle1] = useHandleChange('one');
  const [value2, handle2] = useHandleChange('two');
  const [value3, handle3] = useHandleChange('three');
  return <div>
    <div>
      <input onChange={handle1} value={value1} />
      <input onChange={handle2} value={value2} />
      <input onChange={handle3} value={value3} />
    </div>
    <h2>States:</h2>
    <ul>
      <li>{value1}</li>
      <li>{value2}</li>
      <li>{value3}</li>
    </ul>
  </div>
}

ReactDOM.render(<App />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="app"></div>

注意使用 React.useCallback 来阻止你的钩子在每次渲染时返回一个新的处理函数。 (我们不需要将 setValue 指定为依赖项,因为 React 保证它永远不会改变)

【讨论】:

    猜你喜欢
    • 2019-11-01
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 2021-08-03
    • 2020-11-13
    • 2018-12-10
    • 1970-01-01
    相关资源
    最近更新 更多