首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >props中的“‘value”和状态为“thisValue”的反模式?

props中的“‘value”和状态为“thisValue”的反模式?
EN

Stack Overflow用户
提问于 2019-11-01 11:26:18
回答 2查看 168关注 0票数 3

我最近发现自己写了很多代码,看起来像这样:

代码语言:javascript
运行
复制
const SomeComponent: React.FunctionComponent<SomeComponentProps> = props => {
  const { value } = props;
  const [thisValue, setThisValue] = React.useState(value);

  const handleChange = React.useCallback(e => {
    setThisValue(e.target.value);
  }, []);
 ....

Full example on CodePen.

在这里,我从props传入一个初始化值,然后在组件中修改该值。

它做了我想做的,但我开始怀疑它了。

这是反模式吗?

EN

回答 2

Stack Overflow用户

发布于 2019-11-01 11:54:33

这是一篇不错的(有点旧的)文章,讨论了使用props初始化状态:

https://medium.com/@justintulk/react-anti-patterns-props-in-initial-state-28687846cc2e

React文档称其为反模式:

在getInitialState中使用属性来生成状态通常会导致“事实来源”的重复,即实际数据所在的位置。这是因为getInitialState只在组件首次创建时调用。

文档中有一个例外,那就是:

仅当有意忽略属性更新时才使用此模式。在这种情况下,将属性重命名为initialColor或defaultColor是有意义的。然后,您可以在必要时通过更改组件的键来强制组件“重置”其内部状态。

话虽如此,我也发现自己时不时地这样做。

我发现它有用的一个例子是允许用户编辑复杂状态的组件。您可以使用props初始化状态,组件将在内部处理对此状态的更改。如果要在道具更改时重置状态,则有两种选择:

第一种方法是侦听更改并调用setState,如下所示:

代码语言:javascript
运行
复制
componentDidUpdate(prevProps, prevState) {
  if (prevProps.inputValue !== this.props.inputValue) {
    this.setState({ inputVal: this.props.inputValue })
  }
}

推荐的选项是给组件一个键,这个键取决于应该触发重置的道具。然后当属性改变时,组件状态将被重新初始化:

代码语言:javascript
运行
复制
<MyComponent initProp={someValue} key={`key_${someValue}`/>

我只建议将这些选项用于复杂的状态。在大多数示例中,父组件可以保持此状态,内部组件可以使用回调来更新父组件的更改。

票数 3
EN

Stack Overflow用户

发布于 2019-11-01 18:52:52

这是一个反模式的例子,在这个例子中,你不让道具领先,只在挂载或构造函数上设置状态。我正在尝试创建一个有状态的表单组件,但在用户提交它时会向消费者(父组件)发出信号。消费者可以选择重置表单:

代码语言:javascript
运行
复制
function App() {
  const [initial, setInitial] = React.useState({
    name: 'init',
  });
  const submit = React.useCallback(form => {
    console.log('form is:',form);
  }, []);
  return (
    <div>
      <button onClick={() => setInitial({ name: 'reset' })}>
        reset
      </button>
      <Form initial={initial} submit={submit} />
    </div>
  );
}

function Form({ initial, submit }) {
  const [form, setForm] = React.useState(initial);
  const onChange = React.useCallback(e => {
    const name = e.target.value;
    setForm(form => ({ ...form, name }));
  }, []);
  const onSubmit = React.useCallback(
    e => {
      e.preventDefault();
      setForm(form => {
        submit(form);
        return form;
      });
    },
    [submit]
  );
  //witout this effect reset will not work
  React.useEffect(() => setForm(initial), [initial]);
  return (
    <form onSubmit={onSubmit}>
      <input
        type="text"
        value={form.name}
        onChange={onChange}
      />
      <button type="submit">Save</button>
    </form>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58653738

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档