1

I am a beginner starting out in react and having difficulties in state management while working with react-redux and useState. In the below code I am basically following a tutorial which passes in the this.state to the dispatch action createProject in the handleSubmit function as seen below.

class CreateProject extends Component {
  state = {
    title: '',
    content: ''
  }
  handleChange = (e) => {
    this.setState({
      [e.target.id]: e.target.value
    })
  }
  handleSubmit = (e) => {
    e.preventDefault();
    // console.log(this.state);
    this.props.createProject(this.state);
  }
  render() {
    return (
      <div className="container">
        <form className="white" onSubmit={this.handleSubmit}>
          <h5 className="grey-text text-darken-3">Create a New Project</h5>
          <div className="input-field">
            <input type="text" id='title' onChange={this.handleChange} />
            <label htmlFor="title">Project Title</label>
          </div>
          <div className="input-field">
            <textarea id="content" className="materialize-textarea" onChange={this.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 => {
  return {
    createProject: (project) => dispatch(createProject(project))
  }
}

export default connect(null, mapDispatchToProps)(CreateProject)

Now, instead of using Class component I am using the functional component and using the useState hook. in the handleSubmit function how can I pass the state to the this.props.createProject() as this.props is not defined in-case of functional component and how to pass the state in place of this.state, will it be the projectinfo which stores the state or something else, I'm confused.

TLDR; I want to rewrite the this.props.createProject(this.state) line from the perspective of useState hook.

Below is the code I have written:

const CreateProject = () => {

    const [title, setTitle] = useState('');
    const [content, setContent] = useState('');


    const handleSubmit = (e) => {
        e.preventDefault();

        const projectinfo = { title, content }

        this.props.createProject(projectinfo);

    }
    return(
        <div className="container">
            <form onSubmit={handleSubmit} className="white">
                <h5 className="grey-text text-darken-3">Create Task</h5>
                <div className="input-field">
                    <label htmlFor="title">Title</label>
                    <input type="text" value={title} id="title" onChange={(e) => setTitle(e.target.value)} />
                </div>
                <div className="input-field">
                    <label htmlFor="content">Content</label>
                    <textarea id="content" className="materialize-textarea" onChange={(e) => setContent(e.target.value)}></textarea>
                   
                </div>
                <button className="btn pink lighten-1 z-depth-0">Create</button>
            </form>
        </div>
    );

}

const mapDispatchToProps  = (dispatch) =>{
    return{
        createProject: (project) => dispatch(createProject(project)),
    };
}

export default connect(null, mapDispatchToProps)(CreateProject);

Any help or clues to understand this would be appreciated. Thank you!

nikkbh
  • 35
  • 4

2 Answers2

1

Your dispatch isn't working because you're trying to access it via this.props. Assuming that createProject call inside the dispatch call in mapDispatchToProps is valid and there is a createProject function available in the scope of that file, what you need to do is this:

const CreateProject = (props) => { // Get props from the parameter.

    const [title, setTitle] = useState('');
    const [content, setContent] = useState('');


    const handleSubmit = (e) => {
        e.preventDefault();

        const projectinfo = { title, content }

       props.createProject(projectinfo); // Replace this.props and use props

    }
    return(
        <div className="container">
            <form onSubmit={handleSubmit} className="white">
                <h5 className="grey-text text-darken-3">Create Task</h5>
                <div className="input-field">
                    <label htmlFor="title">Title</label>
                    <input type="text" value={title} id="title" onChange={(e) => setTitle(e.target.value)} />
                </div>
                <div className="input-field">
                    <label htmlFor="content">Content</label>
                    <textarea id="content" className="materialize-textarea" onChange={(e) => setContent(e.target.value)}></textarea>
                   
                </div>
                <button className="btn pink lighten-1 z-depth-0">Create</button>
            </form>
        </div>
    );

}

const mapDispatchToProps  = (dispatch) =>{
    return{
        createProject: (project) => dispatch(createProject(project)),
    };
}

export default connect(null, mapDispatchToProps)(CreateProject);

This would work. I hope this answered and solved your issue.

rishichawda
  • 372
  • 2
  • 10
  • Thank you for the answer, but if I remove props.createProject(projectinnfo) then how would I pass the state to the dispatch action? – nikkbh Mar 26 '21 at 08:19
  • Hi. You don't have to remove it, just replace the line with what I gave in the answer. I'm guessing you looked at it before I had updated. I had fixed my wording after I wrote my original answer, but probably it didn't update for you at the time. – rishichawda Mar 26 '21 at 17:50
  • I see you took the `useDispatch` route. I didn't suggest it because I assumed you were not using it based on your comfort level. A lot of people I know have been taking their time completely moving to hooks while my colleagues and I jumped right in when hooks had been introduced. – rishichawda Mar 26 '21 at 17:53
  • Yeah, I am also pretty much new to hooks and it eases working with state, so `useDispatch` worked for me and pretty easy to understand. – nikkbh Mar 27 '21 at 06:28
  • Glad it worked out for you. Cheers! – rishichawda Mar 27 '21 at 12:47
1

Just want to add some way to do it using react hooks (specifically useDispatch).

With hooks, you don't need to use connect() and mapDispatchToProps. Instead, you can do it like this:

const CreateProject = () => {
  const dispatch = useDispatch();
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');

  const handleSubmit = (e) => {
      e.preventDefault();

      const projectinfo = { title, content }

      // Use dispatch here
      dispatch(createProject(projectinfo));
  }

  return(
    <div className="container">
        <form onSubmit={handleSubmit} className="white">
            <h5 className="grey-text text-darken-3">Create Task</h5>
            <div className="input-field">
                <label htmlFor="title">Title</label>
                <input type="text" value={title} id="title" onChange={(e) => setTitle(e.target.value)} />
            </div>
            <div className="input-field">
                <label htmlFor="content">Content</label>
                <textarea id="content" className="materialize-textarea" onChange={(e) => setContent(e.target.value)}></textarea>
               
            </div>
            <button className="btn pink lighten-1 z-depth-0">Create</button>
        </form>
    </div>
  );
}

export default CreateProject

createProject() is your action creators.

You can read more about useDispatch here: https://react-redux.js.org/api/hooks#usedispatch