我是redux的新手,并按照this tutorial创建了一个带有react和redux的简单博客应用程序。我已经完成了,但是我注意到componentWillRecieveProps
是being deprecated。我正在尝试用更多最新代码替换它,但一直无法理解该怎么做。我已经读过this article的有关将'componentWillReceiveProps'替换为'getDerivedStateFromProps'的知识,但我认为这不是React's blog post正确使用getDerivedStateFromProps的方法,因为用另一种描述替换了其中的一种。
我当前的componentWillRecieveProps
代码:
import axios from "axios";
import React from "react";
import { connect } from "react-redux";
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
title: "",
body: "",
author: ""
};
this.handleChangeField = this.handleChangeField.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
//This is deprecated
componentWillReceiveProps(nextProps) {
console.log(this);
if (nextProps.articleToEdit) {
this.setState({
title: nextProps.articleToEdit.title,
body: nextProps.articleToEdit.body,
author: nextProps.articleToEdit.author
});
}
}
handleSubmit() {
const { onSubmit, articleToEdit, onEdit } = this.props;
const { title, body, author } = this.state;
if (!articleToEdit) {
return axios
.post("http://localhost:8000/api/articles", {
title,
body,
author
})
.then(res => onSubmit(res.data))
.then(() => this.setState({ title: "", body: "", author: "" }));
} else {
return axios
.patch(
`http://localhost:8000/api/articles/${articleToEdit._id}`,
{
title,
body,
author
}
)
.then(res => onEdit(res.data))
.then(() => this.setState({ title: "", body: "", author: "" }));
}
}
handleChangeField(key, event) {
this.setState({
[key]: event.target.value
});
}
render() {
const { articleToEdit } = this.props;
const { title, body, author } = this.state;
return (
<div className="col-12 col-lg-6 offset-lg-3">
<input
onChange={ev => this.handleChangeField("title", ev)}
value={title}
className="form-control my-3"
placeholder="Article Title"
/>
<textarea
onChange={ev => this.handleChangeField("body", ev)}
className="form-control my-3"
placeholder="Article Body"
value={body}
/>
<input
onChange={ev => this.handleChangeField("author", ev)}
value={author}
className="form-control my-3"
placeholder="Article Author"
/>
<button
onClick={this.handleSubmit}
className="btn btn-primary float-right"
>
{articleToEdit ? "Update" : "Submit"}
</button>
</div>
);
}
}
const mapDispatchToProps = dispatch => ({
onSubmit: data => dispatch({ type: "SUBMIT_ARTICLE", data }),
onEdit: data => dispatch({ type: "EDIT_ARTICLE", data })
});
const mapStateToProps = state => ({
articleToEdit: state.home.articleToEdit
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(Form);
如果不赞成使用componentWillRecieveProps
,应该如何更新我的代码?
编辑:使用getDerivedStateFromProps
,nextProps仍然具有先前的值,因此在返回对象时,状态会重新设置为先前的状态,实际上不会进行任何更新。
在这种情况下,尝试使用prevState值不起作用,因为初始prevState值都是空字符串,在组件呈现时会被调用并置于状态,这在初始页面加载时以及单击“编辑”按钮时发生。
static getDerivedStateFromProps(nextProps, prevState) {
if (
JSON.stringify(nextProps.articleToEdit) !==
JSON.stringify(prevState.articleToEdit)
) {
console.log(nextProps);
console.log(prevState);
return {
title: nextProps.articleToEdit.title,
body: nextProps.articleToEdit.body,
author: nextProps.articleToEdit.author
}; // <- is this actually equivalent to this.setState()?
} else {
return null;
}
}
答案 0 :(得分:3)
componentWillReceiveProps()方法。
请记住,您应该始终将当前的道具与如下所示的以前的道具进行比较,如果两者都不相同,则请执行setState,否则会陷入无限的setState警告
在下面的代码处代替componentWillReceiveProps方法
static getDerivedStateFromProps(nextProps, prevState) {
//Below I used JSON.stringify to compare current props with previous props of articleToEdit object
if (JSON.stringify(nextProps.articleToEdit) !== JSON.stringify(prevState.artileToEdit)){
return({
title: nextProps.articleToEdit.title,
body: nextProps.articleToEdit.body,
author: nextProps.articleToEdit.author
});// <- this is setState equivalent
}
return null;
}
编辑:
您无法在getDerivedStateFromProps函数中访问this.props。如果您想访问函数内部的某些先前道具(例如用于比较),则可以在状态内镜像此类值。然后,您可以将nextProps与上面状态存储的值进行比较
检查此线程以更好地了解
https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props
答案 1 :(得分:1)
我的建议是,注意警告,因为使用不当,React会通过替换此生命周期方法来给我们-他们告诉我们仅在确实需要时才这样做,因为可能有更好的方法< / em>(包括较新的getDerivedStateFromProps
)。
根据我在这段代码中收集到的信息,您正在呈现一个表单,让用户与它进行交互,但是在某些情况下,您用props(覆盖组件状态)替换了用户的输入。很容易看出为什么这是一种反模式,但是在不了解有关该应用程序的更多信息的情况下很难重新构造。
我建议将输入的值移到父状态(或创建一个新父级),然后更改为value={props.title}
等。如果在任何情况下都有一个控制表单状态的父级,则您最好一直保持表格状态。
答案 2 :(得分:1)
好的。这是您的应用程序的有效示例。我完全重写了它的结构,以使每个组件都能处理自己的状态和道具集。这些组件还可以重复使用,因此可以放置在任何地方-只要它需要道具即可。
注意:
.jsx
和.js
(有关修复,请参见步骤6)AJAX
请求以利用API
来CRUD
来articles
(例如,表单提交会向post
发送API
请求,这将向数据库添加文章,然后将用户重定向回/articles
,或者可以在发布并更新{{ 1}}状态(包含新数据)。由您自己决定如何处理。但是,如此说来,您真正需要做的唯一事情是,如果您要共享来自两个单独的大量嵌套组件的道具。ShowArticles
和types
文件夹,如下例所示。它使您的代码更易于阅读和模块化。actions
。否则,当应用程序崩溃(并且将会崩溃)时,如果您发现有很多“ index.js”崩溃,将很麻烦。index.js
和server
,具有错误覆盖,拖累等等。我强烈建议您将现有的内容移植到它上。工作示例:https://codesandbox.io/s/4x4kxn9qxw(不幸的是,client
模板不允许导入create-react-app
模块...哦,您会明白的)