简体   繁体   中英

Passing props twice for a Higher Order Component?

I'm building a webpage and realized a common style shared by each component (same background, border, and title style). So I thought I should make an HOC which accepts the inner content of each component as well as a title, and returns an outer component which wraps this inner component and heading. At first I ran into a lot of issues trying to get this to work, being new to React, but now it's finally working but I still don't understand how.

Here is my 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

This is the WrappedComponent:

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

export default BaseBlock(HighlightsBlock)

And this is the 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

And this is how I'm using the component in my app:

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

Now, I can see the HighlightsBlock component receiving props twice (Once when I'm using it in my App with props, and once inside the HOC Baseblock as WrappedComponent ). If I remove props from either of these places it stops working. I don't understand how this is working.

When you render <HighlightsBlock items={this.getHighlights()} title='Highlights' /> you are actually rendering the component returned by HOC which in turn renders your actually HighlightsBlock component as <WrappedComponent {...this.props} />

You can think of HighlightsBlock component to be nested two level deep and hence you need to pass on the props to it, firstly as {...this.props} from within HOC and then receive it as props in functional component

This is because of this.getHighlights() in this line,

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

Every time you pass props to child component this function is getting executed.

To solve this issue, maintain a state value in your parent component and set that value in getHighlights function like,

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

Now you can pass items like,

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM