user14232549
user14232549

Reputation: 413

I am rewriting a class component to a functional component in react-redux-firebase project

I am rebuilding this component. 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

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

Answers (2)

Linda Paiste
Linda Paiste

Reputation: 42288

Problem: Missing name Property on Inputs

FirebaseError: 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.

Redux Hooks

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));

Complete Code

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

Arfan ali
Arfan ali

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

Related Questions