【问题标题】:Passing props to child component将道具传递给子组件
【发布时间】:2018-07-07 16:24:11
【问题描述】:

我似乎无法弄清楚如何将我的道具从我的 App 组件记录到我的子 TotalBox 组件。它一直作为空对象返回。有谁知道如何成功地做到这一点?

App.js

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handler = this.handler.bind(this)
  }

  handler() {
    this.setState({
      value: 0
    })
  }

  render() {

  return (
  <Wrapper>
    <Grid>
      <Row>
        <CostBox/>
        <Input/>
        <TotalBox {...this.props}/>
      </Row>
    </Grid>
  </Wrapper>
)
  }
}

totalBox.js

class TotalBox extends React.Component {
  constructor(props) {
    super(props);
    console.log(this.props); // Object {}
    this.state = {
      value: this.props.value
    }
  }

  render() {
    return (
      <Col md={3}>
        <RightBox>
          <TotalCostHeader>TOTAL COST</TotalCostHeader>
          <TotalCostLabel>{this.state.value}</TotalCostLabel>
        </RightBox>
      </Col>
    )
  }
}

【问题讨论】:

  • 你的 App 组件的 props 是什么?
  • App 组件中的this.props 是什么?
  • 我想传递value 的数值,以便在子组件和其他组件中对其进行操作
  • 所以您在 App 组件中的某个位置有this.props.value?编辑:在我看来你只设置了this.state.value
  • 我认为这就是我通过设置value的状态所做的。

标签: javascript html reactjs constructor components


【解决方案1】:

如前所述,您做错的第一件事是在App 组件中适当地将value 作为道具传递给TotalBox。您确实有一个 this.state.value,它在您的 handler() 函数中完成。

乍一看,解决方案是简单地设置&lt;TotalBox value={this.state.value}/&gt;

但是现在我们的问题是您的状态尚未设置,因为尚未调用 handler() 函数(这是您根据代码实际设置状态的唯一位置)。

如果您希望稍后调用它,您确实需要在 App 组件中将某种占位符值设置为 this.state.value。可能看起来像这样:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handler = this.handler.bind(this)
    this.state = {value: 0} // placeholder value set here
  }

  handler() {
    this.setState({
      value: 0
    })
  }

  render() {

  return (
  <Wrapper>
    <Grid>
      <Row>
        <CostBox/>
        <Input/>
        <TotalBox value={this.state.value}/>
      </Row>
    </Grid>
  </Wrapper>
)
  }
}

或者,如果未设置 state 或 state.value,您可以简单地不渲染 TotalBox 组件。所以在 App 组件中是这样的:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handler = this.handler.bind(this)
    this.state = {} // don't forget to declare the state object itself
  }

  handler() {
    this.setState({
      value: 0
    })
  }

    render() {
        const totalBox = this.state.value ? <TotalBox value={this.state.value}/> : null
          return (
          <Wrapper>
            <Grid>
              <Row>
                <CostBox/>
                <Input/>
                {totalBox}
              </Row>
            </Grid>
          </Wrapper>
        )
          }
}

编辑:您提到要通过子组件更新父组件的状态。这里是如何使用handler 函数的代码:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handler = this.handler.bind(this)
  }

  handler() {
    this.setState({
      value: 0
    })
  }

  render() {

  return (
  <Wrapper>
    <Grid>
      <Row>
        <CostBox/>
        <Input/>
        <TotalBox value={this.state.value} handler={this.handler.bind(this)}/>
      </Row>
    </Grid>
  </Wrapper>
)
  }
}

class TotalBox extends React.Component {
  constructor(props) {
    super(props);
    console.log(this.props); // Object {}
    this.state = {
      value: this.props.value
    }
  }

 // Im using handler as a name for this function just as an example
 // this would be whatever you call as a function to update the state of
 // the parent component.
 handler () {
   // this is the function from your parent component
   // being executed to update its state
   this.props.handler()
 }  

  render() {
    return (
      <Col md={3}>
        <RightBox>
          <TotalCostHeader>TOTAL COST</TotalCostHeader>
          <TotalCostLabel>{this.state.value}</TotalCostLabel>
        </RightBox>
      </Col>
    )
  }
}

【讨论】:

  • 使用“您没有设置this.props.value”这样的措辞可能会造成混淆。您实际上无法设置组件的 this.props 值,它的行为与预期不同。您提到 OP 可能想要使用来自 this.state 的值是正确的,但之前的陈述可能会产生误导。
  • 嗯,我在第一个解决方案中仍然得到一个空对象,并且页面在第二个解决方案中没有呈现。
  • 对于第一个解决方案,我搞砸了渲染代码(现在已修复)。您是否为它传递了 `value={this.state.value}?
  • 我似乎已经开始工作了,现在有没有一种方法可以在子组件中修改该值后,我可以在父组件中注册该值,然后在我的子组件中使用更新后的值组件?
  • 至于第二种方案,可能是因为totalBox 会为空。只有在您期望渲染TotalBox 组件之前设置this.state.value,它才会起作用。在你给出的代码中,this.state.value 实际上是设置的。
【解决方案2】:

@Jason,您需要从父母向孩子发送道具,如下所示:

 <TotalBox value={this.state.value}/>

【讨论】:

  • 如果this.props 包含密钥value,那么OP 对{...this.props} 所做的就是您所建议内容的简写。如果this.props 不包含value 键的值,这仍然不起作用。
  • 对不起,我修好了。您需要单独定义每个道具并将其从父母发送给孩子。
  • &lt;TotalBox {...this.props}/&gt; 是不正确的方法,因为 this.propsApp.js 组件而不是 TotalBox.js 相关。
  • 你在说什么?您在上面提出的建议编译为 React.createElement(TotalBox, {value: this.props.value});(在您修复 props -> state 之前,对于本示例而言无关紧要)。 &lt;TotalBox {...this.props} /&gt; 的 OP 正在做什么编译为 React.createElement(TotalBox, this.props); 如果 this.props.value 存在,并且为了论证,我们假设它确实存在,这两个代码 sn-ps 有何不同?传递的 props 编译为具有相应键的对象,如果 {...obj} 具有相同的键,则它是相同的代码。这里没有魔法。
  • 为了调用TotalBox.js组件,如果我们使用而不是&lt;TotalBox value={this.state.value}/&gt;,我们发送App.js的@987654341 @TotalBox.js,这不是我们的目标。我们应该一个一个地定义所有的 props,然后将它们发送到 'TotalBox.js' 组件。然后在TotalBox.js 组件中,我们将使用...this.props 访问所有props
【解决方案3】:

您真的打算通过this.props,还是您的意思是通过this.state?从代码来看,您似乎想要传递this.state,它具有value 属性并使用传递的value 属性。您还缺少 this.stateApp 组件构造函数中的初始化:

this.state = {
  value: 0,
}

另外,请记住,构造函数只会在组件在首次渲染之前创建时被调用一次。并且以后对传递的道具的更新不会被constructor 捕获。如果您想获取以后的更新,则必须使用 componentWillReceiveProps(nextProps) 组件生命周期方法。

如果您希望传递value 属性,我还建议您不要使用{...this.props} 语法,而是使用显式value={this.props.value}{...this.props} 看起来像是一个干净的解决方案,但它的可读性较差,因为它没有提供您传递给组件的确切内容的上下文。这种语法可能很有用,但这种情况很少见。通常,它是一个通用的高阶组件,它包含另一个组件,并且您希望将道具传递给封闭的组件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2020-12-19
    • 2020-10-08
    • 2021-03-27
    • 2020-09-01
    相关资源
    最近更新 更多