Reputation: 2796
I'm having an error when I'm using propTypes and conditional rendering children.
The error : Warning: Failed prop type: The prop 'rate' is marked as required in 'Rate', but its value is 'undefined'
// index.js
import React, { Component } from "react";
import { render } from "react-dom";
import Rate from "./components/Rate";
import Card from "./components/Card";
class App extends Component {
state = {
loading: true
};
componentDidMount() {
setTimeout(() => this.setState({ loading: false, rate: 5 }), 5000);
}
render() {
return (
<Card loading={this.state.loading}>
<Rate rate={this.state.rate} />
</Card>
);
}
}
render(<App />, document.getElementById("root"));
// rate.js
import React from "react";
import PropTypes from "prop-types";
const Rate = ({ rate }) => (
<div>
<span>{rate}/10</span>
</div>
);
Rate.propTypes = {
rate: PropTypes.number.isRequired
};
export default Rate;
I have reproduced my error here : https://codesandbox.io/embed/qvx8q78ypw
I want to render children element only if loading is set to false.
EDIT : I don't understand why I get this error on Rate component until it is rendered
I don't understand why I get this error.
Thanks for help
Upvotes: 1
Views: 2676
Reputation: 17608
You can use a default prop value for the time being:
Rate.defaultProps = {
rate: 0
};
You are not rendering Card conditionally as @Cody Moniz told in the answer. You are always rendering it. Probably in your Card component you are hiding or showing something depends on the loading prop that you passed to it. Do not bother like that, just use conditional rendering properly and clean up your Card component a little bit maybe.
render() {
return !this.state.loading && (
<Card>
<Rate rate={this.state.rate} />
</Card>
);
}
Here, if React gets null or false it renders nothing. So, when your loading state is false you render nothing, after it changes to true then the second part evaluated and renders your component. Second part is not evaluated until the first one is true with logical &&
operator. This is a nice and clean way to do conditional rendering especially you want to show nothing in the first condition.
If you want to show something about Card (means render it) but only render Rate component conditionally, you can apply this logic in your Card component with loading prop that your Card component gets.
Upvotes: 2
Reputation: 5065
<Rate>
is still being rendered in <App>
, the only thing <Card>
does is hide or show the already-rendered this.props.children
element(s) passed to it.
Upvotes: 1
Reputation: 20554
You're trying to load the <Rate />
component with a rate
prop equal to this.state.rate
in <App />
. Your App component state has nothing set for this.state.rate
so while <Rate />
expects PropTypes.Number
, it's actually getting undefined
. That's why it's complaining.
To solve, you could set the state for <App />
to something like:
state = {
loading: true
rate: 0,
};
Upvotes: 0