Reputation: 413
I am rebuilding this component. https://github.com/ayush221b/MarioPlan-react-redux-firebase-app/blob/master/src/Components/projects/CreateProject.js
however, I don't know how to rewrite mapStateToProps and mapDispatchToProps
The error says
FirebaseError: Function addDoc() called with invalid data. Document fields must not be empty (found in field `` in document projects/5to35LFKROA5aKMXpjqy)
The project seems not be dispatched??
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)
Upvotes: 2
Views: 90
Reputation: 42288
name
Property on InputsFirebaseError: Function addDoc() called with invalid data. Document fields must not be empty (found in field `` in document projects/5to35LFKROA5aKMXpjqy)
This error doesn't have anything to do with mapStateToProps
. You are failing this test by passing a an object with an empty key.
{
title: "Some Title",
content: "some content",
'': "some value"
}
So where does that empty key come from? Well you are setting values in the state with a dynamic key based on the event.target.name
.
const handleChange = (event) => {
setState({
...state,
[event.target.name]: event.target.value
});
};
When you change the input
or the textarea
, what is event.target.name
? Take a look at your code.
<input type="text" id="title" onChange={handleChange} />
There is no name property!
You must either:
A) Add a name
to each of the inputs that corresponds to the property which you want to update in the state
.
<input type="text" id="title" name="title" onChange={handleChange} />
or B) Change your setState
to use event.target.id
, which is already set.
const handleChange = (event) => {
setState({
...state,
[event.target.id]: event.target.value
});
};
I recommend B) as it looks like that's what you were doing before.
Integrating with the redux hooks is very simple. Easier than dealing with connect
, in my opinion.
Access auth
from a selector.
const auth = useSelector((state) => state.firebase.auth);
Call useDispatch
add the top-level of your component to access dispatch
.
const dispatch = useDispatch();
In your handleSubmit
, call dispatch
with the results of your action creator.
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>
);
};
Upvotes: 2
Reputation: 439
in the functional component, you can use hooks like "useSelector" to get the store states
const firebase = useSelector(state => state.firebase)
and "useDispatch" to trigger an action
const dispatch = useDispatch()
<button onClick={() => dispatch({ type: 'GET_DATA' })} >Click me</button>
don't forget to import
import { useSelector, useDispatch } from 'react-redux'
Upvotes: 2