Reputation: 2204
From the App
component, I bring status = paid
to the Todo
component, then to theEditForm
component. The contents of this.props.status = 10
attempts to display ininput select
. In select, I put value = {this.props.status}
. Select should display paid
. It displays unpaid
. Status value is 10, but I want display
instead of 10 I want to display 'paid'
Code here: https://stackblitz.com/edit/react-xsl5mf
class EditForm extends React.Component {
render() {
return (
<select defaultValue ={this.props.status} onChange={(e) => this.props.handleChangeStatus(e)}>
<option value="0">Unpaid</option>
<option value="10">paid</option>
<option value="20">free</option>
</select>
)
}
}
class Todo extends Component {
state = {
status: ''
}
handleChangeStatus = (evt) => {
this.setState({
status: evt.target.value
})
}
componentDidMount = () => {
const { todo } = this.props;
this.setState({
status: todo.status
})
}
render() {
return (
<EditForm
handleChangeStatus={this.handleChangeStatus}
status={this.props.status}
/>
)
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
todos: [
{
status: 10 //paid
}
]
};
}
render() {
return (
<div>
<ul>
{
this.state.todos
.map((todo, index) =>
<Todo
key={index}
index={index}
todo={todo}
/>
)
}
</ul>
</div>
);
}
}
Upvotes: 0
Views: 56
Reputation: 1762
In your component Todo you are passing the this.props.status which is undefined since such a prop does not exist.
In your Todo componetn when it is mounted you set the status to be todo.status
However here it receives this.props.status whereas you should be passing this.props.todo.status since componentDidMount is uncessary here and it won't actually reflect the status since it will trigger it after the render()
method. You could use componentDidMount but it is deprecated
so you can do what you are doing inside the constructor.
If you still want to keep the values as integer then you will have to map them to the strings.
const prices = {
paid: 20,
unpaid: 10,
free: 0
}
<EditForm
handleChangeStatus={this.handleChangeStatus}
status={this.props.status}
/>
On the other hand your values do not match the value that's being sent to the component. It should be as following since if you define value='10' and has the string of paid it won't know which value is the default value. Your event handler will update the status to be the price in this case.
<select defaultValue={this.props.status} onChange={(e) => this.props.handleChangeStatus(e)}>
<option value="unpaid">unpaid</option>
<option value="paid">paid</option>
<option value="free">free</option>
</select>
Take a look at this example here
Upvotes: 0
Reputation: 17654
In Todo
: you call EditForm
with status={this.props.status}
, this.props.status
is undefined
and should be this.state.status
In EditForm
: use value
instead of defaultValue
and the values of the options are not the same as the status, you'd get paid
in the props as status
but the option
's value is 20
, you'll need to handle that, for the snippet below i chnged it to paid
:
class EditForm extends React.Component {
render() {
return (
<select value ={this.props.status} onChange={(e) => this.props.handleChangeStatus(e)}>
<option value="0">Unpaid</option>
<option value="10">paid</option>
<option value="20">free</option>
</select>
)
}
}
class Todo extends React.Component {
state = {
status: ''
}
handleChangeStatus = (evt) => {
this.setState({
status: evt.target.value
})
}
componentDidMount = () => {
const { todo } = this.props;
this.setState({
status: todo.status
})
}
render() {
return (
<EditForm
handleChangeStatus={this.handleChangeStatus}
status={this.state.status}
/>
)
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
todos: [
{
status: '10'
}
]
};
}
render() {
return (
<div>
<ul>
{
this.state.todos
.map((todo, index) =>
<Todo
key={index}
index={index}
todo={todo}
/>
)
}
</ul>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 1
Reputation: 1114
You are doing a couple things wrong:
this.props.status
inside Editform doesn't exist.The value inside the option elements is incorrect, they should match the string that you are passing into the defaultValue.
import React, { Component } from 'react'; import { render } from 'react-dom'; import Hello from './Hello'; import './style.css';
class EditForm extends React.Component { render() { return ( this.props.handleChangeStatus(e)}> Unpaid paid free ) } }
class Todo extends Component {
state = { status: '' }
handleChangeStatus = (evt) => { this.setState({ status: evt.target.value }) }
render() { console.log(this.state) return (
<EditForm
handleChangeStatus={this.handleChangeStatus}
status={this.props.todo.status}
/>
)
} }
class App extends React.Component { constructor() { super();
this.state = {
todos: [
{
status: 'paid'
}
]
};
}
render() { return (
Upvotes: 0
Reputation: 1021
Actually the EditForm
should be like below
<EditForm
handleChangeStatus={this.handleChangeStatus}
status={this.state.status}
/>
And before passing it defaultValue
do conversion and map paid to 10
.
Upvotes: 0