【问题标题】:React.js: Should parent or component manage state?React.js:父级或组件应该管理状态吗?
【发布时间】:2018-07-27 15:44:31
【问题描述】:

我有一个包含<input type="text"> 的“日期输入”组件。

其目的是允许用户输入有效日期(例如,mm/dd/yyyy)。

一旦用户输入了一个有效的日期,组件的父组件就会收到该日期。

基于此 - 我试图弄清楚组件或父级是否应该管理状态。

如果我将其设置为 管理状态:

render() {
    return (
        <div>
            <input type="text" value={this.props.value} onChange={this.props.handleChange} />
        </div>
    );
}

...这不好,因为每次更改都会通知父级,并且当用户键入时,道具将设置为所有“草稿”值(例如,“07/2”)。

这表明我应该进行设置,以便 组件 管理它自己的状态:

class InputDateWithLabel extends Component {

    constructor(props) {
        super(props);

        this.state = {
            value: formatDate(this.props.value) // formatDate() formats a date object into an 'mm/dd/yyyy' string
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleBlur = this.handleBlur.bind(this);

    }

    handleChange(event) {
        // use setState() to update this.state.value so the <input> shows what the user types
    }

    handleBlur(event) {
        // if the user entered a valid date,
        // convert the user's input to a date object,
        // and communicate that to the parent. E.g.,:
        this.props.onChange([new date]);
        // Otherwise, handle the "error"
    }

    render() {
        return (
            <input type="text" value={this.state.value} onChange={this.handleChange} onBlur={this.handleBlur} />
        );
    }
}

这个版本完全按照我想要的方式工作,除了多了一个要求...

根据我的应用程序中其他地方可能发生的事情,父级可能需要在此组件中设置日期。但是 - 现在组件正在管理它自己的状态 - 当父级更改 props.value 时,我的组件将忽略它。

React 文档在这里解决了这种情况:You Probably Don't Need Derived State

但他们的解决方案似乎并不适用:

避免上述问题的一种方法是从我们的组件中完全删除状态。

这不好,因为我不想让父母负责验证用户的日期输入。我的组件应该是独立的,包括日期验证,这意味着它需要管理用户输入的“草稿状态”。

另一种选择是让我们的组件完全拥有“草稿”状态。在这种情况下,我们的组件仍然可以接受初始值的 prop,但它会忽略对该 prop 的后续更改

这不好,因为我需要保留父级更改值的能力在适当的时候。

React 文档的其余部分提到了一些其他可能性 (getDerivedStateFromProps),但它竭尽全力强调 它们可能不正确。 (注意文章标题!)

这似乎并不罕见,因此必须有一种清晰、简单、有据可查的方法来处理它,这是正确的“反应方式”。那是什么?

【问题讨论】:

  • 我认为你应该选择这个组件是受控还是不受控。为什么不控制它并在值通过验证时调用onChange 回调?
  • 使用&lt;input value={this.state.value}&gt; 不是一个好方法。这是一个已知的容易出错的地方。
  • @Sagivb.g 根据 React 文档,“在大多数情况下,您应该使用受控组件”。这似乎是做到这一点的“正确方法”,这就是我想做的。所以 - 我正在尝试使用受控组件来实现我的目标,其中组件管理它自己的状态,但是父级仍然有能力设置值 在适当的时候。你如何使用受控组件来做到这一点?
  • “组件管理自己的状态”,这与受控组件相反。
  • @IsaacFerreira 我知道&lt;input value={this.state.value}&gt; 容易出错。但是更好的方法是什么?我不想使用&lt;input value={this.props.value}&gt;,因为这意味着组件正在向父级发送所有草稿 输入的版本(例如,“07/2”),而不是有效的日期对象。

标签: javascript reactjs


【解决方案1】:

在您的情况下,让组件管理它自己的状态似乎并没有那么糟糕,但是您需要添加 componentWillReceiveProps 来添加另一段代码来管理。

componentWillReceiveProps(nextProps) {
    this.setState({
        value: formatDate(nextProps.value)
    });
}

【讨论】:

  • componentWillReceivePropsdeprecated and should be avoided
  • 啊,那我自己就不用了。谢谢。
  • @Jason - 感谢您的建议。但是,React 文档很清楚你不应该这样做。 componentWillReceiveProps 已被弃用,他们将其描述为反模式
  • 你想知道的关于this blog post的变化。
  • 对此有新的方法和替代方案,但它被认为是一种反模式,因为它打破了单一的事实来源。你可以让它工作,但它可能会导致严重的错误。
猜你喜欢
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-14
相关资源
最近更新 更多