为高阶组件两次传递道具?

时间:2019-07-02 06:45:03

标签: javascript reactjs

我正在构建一个网页,并实现了每个组件共享的通用样式(相同的背景,边框和标题样式)。因此,我认为我应该制作一个HOC,该HOC接受每个组件的内部内容以及标题,然后返回一个外部组件,该外部组件包装此内部组件和标题。 起初,我遇到了很多问题,试图让它开始工作,这是React的新手,但现在终于可以工作了,但我仍然不知道如何。

这是我的HOC

const BaseBlock = (WrappedComponent) => {
  return class BaseBlock extends Component {
    render () {
      return (
        <div className={styles['base-block']}>
          <div className={styles['container']}>
            <div className={styles['base-block-head']}>
              { this.props.title }
            </div>
            <div className={styles['base-block-body']}>
              <WrappedComponent {...this.props} />
            </div>
          </div>
        </div>
      )
    }
  }
}

export default BaseBlock

这是WrappedComponent:

const HighlightsBlock = (props) => {
  return <ListsComponent items={props.items} />
}

export default BaseBlock(HighlightsBlock)

这是ListsComponent

const ListsComponent = (props) => {
  if (props.items) {
    return (
      <ul className={styles['styled-list']}>
        {props.items.map((item, idx) => {
          return (
            <li key={idx} className={styles['styled-list-item']}>{item}</li>
          )
        })}
      </ul>
    )
  } else return (
    <h3>No highlights</h3>
  )
}

export default ListsComponent

这就是我在应用程序中使用组件的方式:

<HighlightsBlock items={this.getHighlights()} title='Highlights' />

现在,我可以看到HighlightsBlock组件两次接收道具(当我在带有道具的App中使用它,一次在HOC Baseblock中作为WrappedComponent)。如果我从上述任何一个地方取走道具,它将停止工作。我不明白这是怎么回事。

2 个答案:

答案 0 :(得分:0)

渲染<HighlightsBlock items={this.getHighlights()} title='Highlights' />时,实际上是在渲染HOC返回的组件,而HOC返回的组件实际上是将HighlightsBlock的组件渲染为<WrappedComponent {...this.props} />

您可以想到HighlightsBlock组件嵌套了两层,因此您需要将道具传递给它,首先从{...this.props}内部以HOC的形式传递,然后在功能组件中将其作为道具接收

答案 1 :(得分:0)

这是因为此行中有this.getHighlights()

<HighlightsBlock items={this.getHighlights()} title='Highlights' />

每次将props传递给子组件时,此函数都会被执行。

要解决此问题,请在parent组件中维护状态值,然后在getHighlights函数中设置该值,例如,

getHighlights(){
 //you logic to get data
 this.setState({items:data.items}); //considering `data` is object which has `items`
}

现在您可以传递诸如

<HighlightsBlock items={this.state.items} title='Highlights' />