[英]Passing state into child component as props not working
I'm trying to build an example CRUD app with React and React Router, and I can't figure out why state isn't passing into a child component the way I'm expecting it to. 我正在尝试使用React和React Router构建一个示例CRUD应用程序,但我不知道为什么状态没有按照我期望的方式传递给子组件。 When I hit the
edit
route, it renders the Edit
component, which grabs the kitten I want from the database and sends it's info to a Form component which is used both for editing an existing kitten or adding a new one. 当我点击
edit
路径时,它将呈现“ Edit
组件,该组件将从数据库中获取我想要的小猫,并将其信息发送到“表单”组件,该组件用于编辑现有小猫或添加新小猫。
Here's the Edit component: 这是Edit组件:
import React, { Component } from 'react';
import axios from 'axios';
import { match } from 'react-router-dom';
import Form from './Form';
export default class Edit extends Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {
axios.get(`/updateKitten/${this.props.match.params.id}`)
.then(res => {
const kitten = res.data
this.setState({ kitten })
console.log(this.state.kitten.name) //Sammy, or something
})
.catch(err => console.log(err))
}
render() {
return (
<Form
name={this.state.kitten.name} // throws error or undefined
description={this.state.kitten.description} //throws error or undefined
route={this.props.match.params.id}
/>
)
}
}
The Edit component passes name, description, and route to this Form component: Edit组件将名称,描述和路由传递给此Form组件:
import React, { Component } from 'react';
import axios from 'axios';
export default class Add extends Component {
constructor(props) {
super(props)
this.state = { name: this.props.name, description: this.props.description}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
const name = e.target.name;
const value = e.target.value;
this.setState({
[name]: value
});
}
handleSubmit(e) {
axios.post(`/addKitten/${this.props.route}`, this.state)
.then(this.setState({ name: '', description: '' }))
e.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>Name</label>
<input type='text' name="name" value={this.state.name}
onChange={this.handleChange}/>
<label>Description</label>
<input type='text' name="description" value={this.state.description}
onChange={this.handleChange}/>
<input type='submit' value='Submit' />
</form>
)
}
}
And I get the following error: 我得到以下错误:
bundle.js:28950 Uncaught TypeError: Cannot read property 'name' of undefined
from trying to send that info as props to the Form
component. 尝试将这些信息作为道具发送到
Form
组件。
What am I doing wrong? 我究竟做错了什么?
When your Edit component loads for the first time, it doesn't have a kitten
. 首次加载“编辑”组件时,它没有
kitten
。 Hence the error. 因此,错误。
What you need to do is the create an empty
kitten. 您需要做的是创建一只
empty
小猫。 In your Edit component... 在您的编辑组件中...
this.state = { kitten: {name:''} }
This will set the kitten's name to an empty string on the very first mount/render of your component. 这会将小猫的名字在组件的第一次安装/渲染时设置为空字符串。
Two things, 两件事情,
First: In your edit component, you have not initialised kitten state and you are setting it based on the API result. 首先:在您的编辑组件中,您尚未初始化小猫状态,而是根据API结果进行设置。 However, componentDidMount is called after the component has been called and hence the DOM has been rendered once and the first time it did not find any value as
this.state.kitten.name
or this.state.kitten.description
. 但是,在组件被调用之后将调用componentDidMount,因此DOM已被渲染一次,并且第一次没有找到任何值为
this.state.kitten.name
或this.state.kitten.description
值。
Its only after the API is a success that you set the kitten state. 只有在API成功后,您才能设置小猫状态。 Hence just make a check while rendering.
因此,只需在渲染时进行检查即可。
Second: You have console.log(this.state.kitten.name)
after the setState
function. 第二:在
setState
函数后面有console.log(this.state.kitten.name)
。 However setState is asynchronous
. 但是
setState is asynchronous
。 See this question: 看到这个问题:
Change state on click react js 更改点击React JS的状态
and hence you need to specify console.log in setState callback 因此,您需要在setState回调中指定console.log
You code will look like 您的代码看起来像
export default class Edit extends Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {
axios.get(`/updateKitten/${this.props.match.params.id}`)
.then(res => {
const kitten = res.data
this.setState({ kitten }. function() {
console.log(this.state.kitten.name) //Sammy, or something
})
})
.catch(err => console.log(err))
}
render() {
return (
<Form
name={this.state.kitten.name || '' }
description={this.state.kitten.description || ''}
route={this.props.match.params.id}
/>
)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.