reactjsfetch-apireact-select

How to make fetch in this React class?


I know how to make fetch to my backend using functions in my react component, but I needed a dropdown menu so I found an example in react-select page, but that example is made in a class.

Clean example I found in internet is this, for import react-select it is necesary to run command npm install react-select:

import React, { Component, Fragment, useEffect } from "react";
import Select from "react-select";

const options = [
  { value: "red", label: "red" },
  { value: "blue", label: "blue" },
  { value: "green", label: "green" }
];

export default class CrearPost extends Component {
  state = {
    selectedOption: null
  };
  handleChange = selectedOption => {
    this.setState({ selectedOption });
    // Option selected: { value: "red", label: "red" }
    console.log(`Option selected:`, selectedOption);
  };
  render() {
    return (
      <div align="center">
      <Fragment>
        <Select
          className="basic-single"
          classNamePrefix="select"
          defaultValue={options[0]}
          isDisabled={false}
          isLoading={false}
          isClearable={true}
          isRtl={false}
          isSearchable={true}
          name="color"
          options={options}
          onChange={this.handleChange}
        />
      </Fragment>
      <input
        type="text"
        placeholder="body"
      />
      <button>
        Submit post
      </button>
      </div>
    );
  }
}

And looks like this: enter image description here

So I decided to try to make fetch, and what I tried is this:

import React, { Component, Fragment, useEffect, useState } from "react";
import Select from "react-select";
import { useHistory } from "react-router-dom"; 

const options = [
  { value: "red", label: "red" },
  { value: "blue", label: "blue" },
  { value: "green", label: "green" }
];

export default class CrearPost extends Component {
  state = {
    selectedOption: null
  };
  handleChange = selectedOption => {
    /*I added all this*/ 
  const [title, setTitle] = useState("");
  const [body, setBody] = useState("");

    const PostData = () => {
      fetch('/createpost', { /*This route is in my nodejs server*/ 
        method:'post',
        headers:{
          'Content-Type':'application/json',
          Authorization: "Bearer " + localStorage.getItem("jwt")
        },
        body:JSON.stringify({
          title,
          body
        })
      }).then(res=>res.json())
      .then(data=>{
        console.log(data)
        if(data.error){
          alert(data.error)
        }
        else{
          alert('Post created')
          history.push('/')
        }
      }).catch(err=>{
        console.log(err)
      })
    }
  };
  render() {
    return (
      <div align="center">
      <Fragment>
        <Select
          className="basic-single"
          classNamePrefix="select"
          defaultValue={options[0]}
          isDisabled={false}
          isLoading={false}
          isClearable={true}
          isRtl={false}
          isSearchable={true}
          name="color"
          options={options}
          value={title}/*I added this*/ 
          onChange={(e) => setTitle(e.target.value)}/*I added this*/ 
        />
      </Fragment>
      <input
        type="text"
        placeholder="body"
        value={body}/*I added this*/ 
        onChange={(e) => setBody(e.target.value)}/*I added this*/ 
      />
      <button onClick={() => PostData()}/*I added this*/>
        Submit post
      </button>
      </div>
    );
  }
}

But I just get this fail in my project: enter image description here

I hope someone could help me, thanks.


Solution

  • Class component is a stateful component and has its own state. So you don't need to useState in class component. Just try out change your state to:

    this.state = {
        title: "",
        body: ""
      };
    

    And don´t forget to delete your states consts