我正在重建这个组件。https://github.com/ayush221b/MarioPlan-react-redux-firebase-app/blob/master/src/Components/projects/CreateProject.js
https://github.com/ayush221b/MarioPlan-react-redux-firebase-app/blob/master/src/store/actions/projectActions.js
然而,我不知道如何重写mapStateToProps和mapDispatchToProps
错误提示
FirebaseError:函数addDoc()调用无效数据。文档字段不能为空(在文档项目/5to35LFKROA5aKMXpjqy字段' '中找到)
项目似乎没有被调度??
import {Component ,useState} from 'react'
import {connect} from 'react-redux'
import {createProject} from '../../store/actions/projectActions'
import { useForm } from "react-hook-form";
import { Redirect } from 'react-router-dom'
const CreateProject = (props) => {
const [state, setState] = useState({
title: "",
content: ""
});
const handleChange = event => {
setState({ ...state, [event.target.name]: event.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(state);
props.createProject(state);
props.history.push('/');
}
const { auth } = props;
return (
<div className="container">
<form className="white" onSubmit={handleSubmit}>
<h5 className="grey-text text-darken-3">Create a New Project</h5>
<div className="input-field">
<input type="text" id='title' onChange={handleChange} />
<label htmlFor="title">Project Title</label>
</div>
<div className="input-field">
<textarea id="content" className="materialize-textarea" onChange={handleChange}></textarea>
<label htmlFor="content">Project Content</label>
</div>
<div className="input-field">
<button className="btn pink lighten-1">Create</button>
</div>
</form>
</div>
)
}
const mapDispatchToProps = (dispatch) => {
console.log("a"+dispatch);
return {
createProject: (project) => dispatch(createProject(project))
}
}
const mapStateToProps = (state) =>{
return{
auth: state.firebase.auth
}
}
export default connect(mapStateToProps,mapDispatchToProps)(CreateProject)
在函数组件中,你可以使用"useSelector"获取存储状态
const firebase = useSelector(state => state.firebase)
和"useDispatch"触发一个动作
const dispatch = useDispatch()
<button onClick={() => dispatch({ type: 'GET_DATA' })} >Click me</button>
不要忘记导入
import { useSelector, useDispatch } from 'react-redux'
问题:输入上缺少name
属性
FirebaseError:函数addDoc()调用无效数据。文档字段不能为空(在文档项目/5to35LFKROA5aKMXpjqy字段' '中找到)
这个错误与mapStateToProps
没有任何关系。您传递了一个带有空键的对象,将导致测试失败。
{
title: "Some Title",
content: "some content",
'': "some value"
}
那么空键是从哪里来的呢?好吧,你正在使用基于event.target.name
的动态密钥设置状态值。
const handleChange = (event) => {
setState({
...state,
[event.target.name]: event.target.value
});
};
当你改变input
或textarea
时,event.target.name
是什么?看一下你的代码。
<input type="text" id="title" onChange={handleChange} />
没有name属性!
你必须:A)在每个输入中添加一个name
,对应于你想要更新的state
中的属性。
<input type="text" id="title" name="title" onChange={handleChange} />
或B)更改您的setState
使用event.target.id
,这是已经设置的。
const handleChange = (event) => {
setState({
...state,
[event.target.id]: event.target.value
});
};
我推荐B),因为看起来你以前就是这么做的。
回来的钩子与redux钩子集成非常简单。在我看来,比处理connect
更容易。
从选择器访问auth
。
const auth = useSelector((state) => state.firebase.auth);
调用useDispatch
,添加组件的顶层以访问dispatch
。
const dispatch = useDispatch();
在你的handleSubmit
中,调用dispatch
和你的行动创建者的结果。
dispatch(createProject(state));
完整代码
const CreateProject = (props) => {
const auth = useSelector((state) => state.firebase.auth);
const dispatch = useDispatch();
const [state, setState] = useState({
title: "",
content: ""
});
const handleChange = (event) => {
setState({ ...state, [event.target.id]: event.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(state);
dispatch(createProject(state));
props.history.push("/");
};
return (
<div className="container">
<form className="white" onSubmit={handleSubmit}>
<h5 className="grey-text text-darken-3">Create a New Project</h5>
<div className="input-field">
<input type="text" id="title" onChange={handleChange} />
<label htmlFor="title">Project Title</label>
</div>
<div className="input-field">
<textarea
id="content"
className="materialize-textarea"
onChange={handleChange}
/>
<label htmlFor="content">Project Content</label>
</div>
<div className="input-field">
<button className="btn pink lighten-1">Create</button>
</div>
</form>
</div>
);
};