0
votes

I'd like to know, how to handle the PropTypes Error when passing a component as a child:

Failed prop type: The prop `value` is marked as required in `ChildComponent`, but its value is `undefined`.

The render works as expected and it's passing the value prop correctly.

I suppose this happens because I am putting the component in the App component's render function without any props. I am only passing those props to the ChildComponent when the ParentComponent maps over its children (which is the ChildComponent).

See the code: https://codesandbox.io/embed/r70r5z3j9q

Is there a way to prevent this from happening? How should I be structuring my components? Am I not supposed to passed components as children?

EDITED: Changed prop "name" to "value". To give it a more generic feel. I tried to simplify the problem in the code. I know I could pass the prop directly in App. The use case would be when the parent is doing calculations and those calculations are supposed to be passed to the child. Without explicitly knowing what these children are. That's why I'm using it as child in the first place.

1
On line 7 of ChildComponent.js, you are setting the prop name to be required. name: PropTypes.string.isRequired. Either provide the prop within <ChildComponent /> of index.js or do not make name prop required. - Gregg

1 Answers

2
votes

You're using cloneElement and you're passing prop to it, not to original element. To fix it, pass props directly:

const App = () => (
  <div>
    <ParentComponent>
      <ChildComponent name="bob" />
    </ParentComponent>
  </div>
);

You could easily pass component as a prop (not children) to you ParentComponent and render it only after it takes some heavy calculations:

const App = () => (
  <div>
    <ParentComponent component={ChildrenComponent} />
  </div>
);

const ParentComponent extends React.Component {
  state = { heavyComputationFinished: false } // initial state

  componentDidMount() {
    runYourHeavyComputations
      .then(() => { this.setState({ heavyComputationsFinished: true }) })
  }

  render() {
    const { component } = this.props
    const { heavyComputationsFinished, name } = this.state

    // return nothing if heavy computations hasn't been finished
    if (!heavyComputationsFinished) { return null }

    // we're getting this component (not its rendering call) as a prop
    return React.render(component, { name })
  }
}