【问题标题】:Getting a child's default props to set the state in the parent in ReactJS获取孩子的默认道具以在 ReactJS 中的父级中设置状态
【发布时间】:2016-01-30 07:31:29
【问题描述】:

类似于Pass props to parent component in React.js,但我只对将子组件的 default 道具放入父组件感兴趣。

那我为什么需要这样做呢?

嗯,我有一个父组件,它呈现一个包含 HTML 表单的子组件。父级的 render() 方法将其状态数据作为 props 向下传递给子级。

最初,子表单应该只包含一些默认数据。从子组件中定义的 defaultProps 获取数据是有意义的。毕竟,我不想为了将其作为默认道具传递给孩子而在父状态中设置默认数据负载。父母不需要定义孩子的默认道具。孩子应该知道自己的默认道具是什么。

所以在我最初的父 render() 中,我将状态保留为未定义。当它作为未定义的道具传递给孩子时,孩子将使用其 defaultProps 代替。这正是我想要的。

时间流逝……

现在用户更改子组件表单上的字段。我通过回调函数将该更改传递回父级,以重新计算父级的新状态。然后我在父组件中调用 setState() 以正常重新渲染所有子组件。

问题是我需要我父母的状态是一个对象,包含更多的嵌套对象,并且正在使用 [React Immutability Helpers][1] 来计算父母中的新状态,如下所示:

handleFormFieldChange(e) {
// reactUpdate imported from 'react-addons-update'
 var newState = reactUpdate(this.state, {
    formData: {values: {formFieldValues: {[e.currentTarget.name]: {$set: e.currentTarget.value}}}}
    });
    this.setState(newState);
}

此代码第一次运行时会抛出错误,因为它正在尝试更新状态值并且没有要更新的状态。 (我没有定义它,记住!)

如果我试图通过为空对象(每个都有嵌套的空对象)设置默认初始状态来解决这个问题,我会遇到一个 catch-22。在第一次渲染时,这些空值将作为空道具传递给子组件,因此覆盖我为子组件设置的 defaultProps。无赖!

据我所知,我需要一个合理的初始状态来传递给子组件,但无需在父组件中再次(重新)定义整个事物。所以在这种情况下,我认为将孩子的 defaultProps 拉到父母中是有意义的,只是为了设置父母的初始状态。

我有办法做到这一点,我稍后会发布。但在我这样做之前,有没有人有更好的方法来做到这一点?一种完全可以避免将 defaultProps 从子级传递给父级的方法?

【问题讨论】:

  • 使用React.ComponentReact.createClass?
  • 我使用的是 ES6 模块,所以 React.Component.

标签: reactjs


【解决方案1】:

如果您使用的是React.Component,那么defaultProps 是类上的静态对象,因此很容易获取。

export default class Child extends React.Component {

  static defaultProps = { ... }

}

// If you don't have es7 static support you can add it after the class def:
Child.defaultProps = { ... }

父母只需要这样做:

Child.defaultProps

访问它。

【讨论】:

  • 确认这对我有用。多米尼克,迟到的感谢。
【解决方案2】:

正如原始帖子中所威胁的那样,这是我将孩子的默认道具发送给父母的方式。

我正在使用 ES6 类和模块模式,使用 Webpack 和 Babel 来处理构建和转译。

所以我有两个文件,我们称它们为 Parent.jsx 和 ChildForm.jsx。以下是 ChildForm.jsx 的外观(注意:不是工作代码!):

class ChildForm extends React.Component {
    render() {
         var fieldValues= this.props.formData.formFieldValues;
         return(
             <form>
                  Field 1: <input type="text"
                              name="field1"
                              value={fieldValues.field1}
                              onChange={this.props.handleFieldChange} />
             </form>
         );
    }
}

export function getDefaultProps() {
   return {
        formData: {
           formFieldValues: {
               field1: "Apples",
               field2: "Bananas"
           }
        }
   };
}

ChildForm.defaultProps = getDefaultProps();

export default ChildForm;

诀窍是将 defaultProps 的设置移动到一个单独的函数中,该函数也是从 ChildForm.jsx 导出的。完成之后,您可能会猜到我将在 Parent.jsx 模块中做什么!一起来看看吧:

import reactUpdate from 'react-addons-update';
import ChildForm from "./ChildForm.jsx";
import {getDefaultProps as getChildFormDefaultProps} from "./ChildForm.jsx";

class Parent extends React.Component {
    constructor(props) {
        super(props);
        var formDefaultProps = getChildFormDefaultProps();
        this.state = {
            formData: formDefaultProps
        };
        this.handleFormFieldChange.bind(this);
    }

    handleFormFieldChange(e) {
        var newState = reactUpdate(this.state, {
            formData: {values: {formFieldValues: {[e.currentTarget.name]: {$set: e.currentTarget.value}}}}
        });
        this.setState(newState);
    }

    render() {
        return (
            <div>
                <ChildForm
                    formData={this.state.formData}
                    handleFieldChange={this.props.handleFormFieldChange} /}
            </div>
        );
    }
}

我从 ChildForm.jsx 模块导入 getDefaultProps 函数,然后使用它在 Parent.jsx 级别设置 ChildForm 的默认状态。然后将该状态作为道具传递给 ChildForm。

虽然这可行,但我不禁觉得它相当笨重。尽管我在 ChildForm.jsx 级别定义了 defaultProps,它们应该在哪里,但实际上它们从未在该级别 使用 作为 defaultProps!相反,它们被传递给 Parent,Parent 使用它们来设置状态,而后者又作为 real 道具传递给 ChildForm。

不过,这比在 Parent 组件中重新定义 ChildForm 组件的默认状态要好。所以现在就可以了,除非你们中的任何好心人可以提出更清洁的建议!

【讨论】:

    猜你喜欢
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 2015-05-19
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多