【发布时间】:2019-10-28 15:13:46
【问题描述】:
我正在使用 React、Redux 和 Firebase 创建一个项目规划应用。我的 Firestore 数据库中的单个项目记录包含一个 Title 和一些 Content。当我去更新一个项目时,我将输入字段的 defaultValues 设置为我想要编辑的项目的正确数据。但是,仅当我对 both 内容和标题输入字段进行更改时,更新才有效。否则,在提交这些值时,数据将被删除,因为本地状态没有看到任何变化,因此将未触及的字段更新为空字符串:""
我曾尝试在 render 方法中设置 EditProject 组件的本地状态,但这是不可能的:
render() {
const { project, auth } = this.props;
if (!auth.uid) return <Redirect to="/signin" />;
if (project) {
this.setState({
title: project.title,
content: project.content
});
...
我也尝试过在componentDidMount 期间设置状态,如下所示:
componentDidMount = () =>{
const { project } = this.props;
this.setState({
title: project.title,
content: project.content
})
}
但是这个问题是mapStateToProps在componentDidMount之前没有映射项目属性
最后,我尝试从父组件传递项目道具,即projectDetails,但我无法成功这样做。我可能在这部分做错了,所以请让我知道是否有使用我拥有的代码的好方法。在ProjectDetails:
<Link to={"/edit/" + docId} key={docId}>
<button className="btn pink lighten-1 z-depth-0">Edit</button>
</Link>
这链接到我正在尝试修复的“损坏”的 EditDetails 组件。
这是我的 EditProject 组件代码
class EditProject extends Component {
state = {
title: "",
content: ""
};
handleChange = e => {
this.setState({
[e.target.id]: e.target.value
});
};
handleSubmit = e => {
e.preventDefault();
let localProject = this.state;
let docId = this.props.docId;
this.props.editProject(localProject, docId);
const projectDetailURL = "/project/" + docId;
this.props.history.push(projectDetailURL);
};
render() {
const { project, auth } = this.props;
if (!auth.uid) return <Redirect to="/signin" />;
if (project) {
return (
<div className="container section project-details">
<div className="card z-depth-0">
<div className="card-content">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Edit Project</h5>
<div className="input-field">
<label htmlFor="title" className="active">
Title
</label>
<input
onChange={this.handleChange}
type="text"
id="title"
defaultValue={project.title}
/>
</div>
<div className="input-field">
<label htmlFor="content" className="active">
Edit Project Content
</label>
<textarea
id="content"
onChange={this.handleChange}
className="materialize-textarea"
defaultValue={project.content}
/>
</div>
<div className="input-field">
<button className="btn pink lighten-1 z-depth-0">
Update
</button>
</div>
</form>
</div>
<div className="card-action grey lighten-4 grey-text">
<div>
Posted by {project.authorFirstName} {project.authorLastName}
</div>
<div>{moment(project.createdAt.toDate()).calendar()}</div>
<div className="right-align" />
</div>
</div>
</div>
);
} else {
return (
<div className="container center">
<p>Loading project...</p>
</div>
);
}
}
}
const mapStateToProps = (state, ownProps) => {
//id = the document id of the project
const id = ownProps.match.params.id;
const projects = state.firestore.data.projects;
const project = projects ? projects[id] : null;
return {
project: project,
auth: state.firebase.auth,
docId: id
};
};
const mapDispatchToProps = dispatch => {
return {
editProject: (project, docId) => dispatch(editProject(project, docId))
};
};
export default compose(
connect(
mapStateToProps,
mapDispatchToProps
),
firestoreConnect([
{
collection: "projects"
}
])
)(EditProject);
访问编辑页面时,如果用户未对输入字段进行任何更改,我希望数据保持不变。
【问题讨论】:
-
控制台记录 props.project 、 props.projects 和 props.id 时的输出是什么。在组件中确实安装了。
-
因为 mapStateToProps 在 componentDidMount 之后完成,它会记录
undefined -
所有这些都给你 undefined ?
-
@Muljayan 在 componentDidMount 中,是的,它只返回未定义的。一旦渲染方法运行,我就可以看到我的组件的所有道具(包括包含
Title和Content的项目道具我需要更新本地状态)。 -
你可以试试console.log(this.props.projects) 在组件中确实挂载了。输出是什么?