david
david

Reputation: 11

How to retrieve data from reactjs and API

I am trying to post form data from react to node backend, How to do thtat ? my React code is :

import fetch from 'isomorphic-fetch';

export function createBio (data) {

    console.log(data);

    return fetch('http://localhost:3001/user/create', {
        method: 'POST',
        mode: 'no-cors',
        body: JSON.stringify(data),
        headers: {

            'Content-Type': 'application/json',

        }

    }).then(res => {
        return res;
    }).catch(err => console.log(err));
}

My NodeJs code

router.post('/create', (req,res,) => {

    var user = new User({title: req.params.title || "Untitled Note", body: req.params.body});
    user.save();

});

How to retrieve data

Upvotes: 1

Views: 1786

Answers (4)

Sigit
Sigit

Reputation: 798

My best way, start create file api.js

import axios from "axios";

export default {
    user: {
        createBio: data => axios.post(`${process.env.API_HOST}/user/create`, {data}).then(res => res),
    }
}

and then you can call function createBio from your component or action if you use redux,

if you get problem Access-Control-Allow-Origin use CORS

Upvotes: 1

Tian
Tian

Reputation: 31

req.param() searches the url path, body, and query string of the request (in that order) for the specified parameter. If no parameter value exists anywhere in the request with the given name, it returns undefined, or the optional defaultValue if specified.

url path parameters (req.params)

e.g. a request /create/4 to route /create/:id has url path params req.params.id :id this id you can change anything you want, but you should add ":" before your parameter

body parameters (req.body)

e.g. a request with a parseable body (e.g. JSON, url-encoded, or XML) has body parameters equal to its parsed value

if you want to get the title, you can write req.body.title

For your case, I recommend you use req.body

Your back-end API

//http://localhost:3001/user/create
    router.post('/create', (req,res) => {

    const user = new User(
          {
          title: req.body.title ===null ? 'Untitled Note' : req.body.title, 
          text: req.body.text
          });
    user.save();

});

You should determine what value your data include

data = {
title: '?',
text: '?'
};

Your Fetch

import fetch from 'isomorphic-fetch';

export function createBio (data) {

    console.log(data);

    fetch('http://localhost:3001/user/create', {
        method: 'POST',
        mode: 'no-cors',
        body: JSON.stringify(data),
        headers: {

            'Content-Type': 'application/json',

        }

    }).then(res => {
        return res;
    }).catch(err => console.log(err));
}

Make sure of your path is right

Any way, I use 'axios' to retrieve data

router.post('/'),
    (req, res) => {
        const newPost = new Post({
            eventTitle: req.body.eventTitle,
            eventText: req.body.eventText
        });

        newPost.save().then(post => res.json(post));
    });

axios

const postData = {
title: '?',
text: '?'
};
     axios
            .post('/api/posts', postData)
            .then(res => console.log(res))
            .catch(err => console.log(err));

Get params

**!But this title should be assigned a value. not a null value**


router.post('/:title'),
        (req, res) => {
            const newPost = new Post({
                eventTitle: req.params.title,
                eventText: req.body.eventText
            });

            newPost.save().then(post => res.json(post));});

   const postData = {
    title: '?',
    text: '?'
    };
         axios
                .post(`/api/posts/${postData.title}`, postData.text)
                .then(res => console.log(res))
                .catch(err => console.log(err));

If you have any questions about fetch, you can use this https://developer.mozilla.org/en-US/.

I hope this is useful for you. Actually, I never used fetch, but axios is same with it.

PS: you should add this for your server.js to get value from the client side. Node.js body parsing middleware. Parse incoming request bodies in a middleware before your handlers, available under the req.body property.

const bodyParser = require('body-parser');
// for parsing application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// for parsing application/json
app.use(bodyParser.json());

Last answer for your comment and your issue.

First, you should add proxy to your client side package.json You cannpm I concurrently to run your server and client simultaneously

Your package.json should include --- I did't create a server json, this may a wrong format. But just a test. The part of ** should be written in the server package.json file! If you don't want to use it, you can just focus on the code, it will fix your problem.

{
  "name": "react",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "axios": "^0.18.0",
    "body-parser": "^1.18.3",
    "concurrently": "^4.0.1",
    "express": "^4.16.4",
    "fetch": "^1.1.0",
    "node-fetch": "^2.2.0",
    "react": "^16.4.2",
    "react-dom": "^16.4.2",
    "react-scripts": "1.1.4",
    "isomorphic-fetch": "^2.2.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    **"server": "node server.js",**
    **"client": "npm start",**
    **"dev": "concurrently \"npm run server\" \"npm run client\"",**
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "proxy": "http://localhost:5000"
}

npm I node-fetch at client side

  import React, {Component} from 'react';
    //import axios from 'axios';
    //import fetch from 'node-fetch';
  import fetch from 'isomorphic-fetch';
    class SendMessage extends Component {
        constructor(props) {
            super(props);
            this.state = {
                title: '',
                text: ''
            };

        this.onChange = this.onChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
    }

    onSubmit(e){
        e.preventDefault();
        const newUser = {
            title: this.state.title,
            text: this.state.text,
        };
        // axios.post('/users/create', newUser)
        //     .then(res => console.log(res))
        //     .catch(err => console.log(err));



        fetch('/users/create', {
            method: 'post',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(newUser)
        }).then(res=>res.json())
            .then(res => console.log(res));


    }

    onChange(e){
        this.setState({[e.target.name]:e.target.value})

    }

    render() {
        return (
            <div>
                <form onSubmit={this.onSubmit}>
                    <input type="text" name='title' onChange={this.onChange} value={this.state.title} placeholder="title"/>
                    <input type="text" name='text' onChange={this.onChange} value={this.state.text} placeholder="text"/>
                    <input type="submit" value="Submit"/>
                </form>
            </div>
        );
    }
}

export default SendMessage;

Server side server.js

const express = require ('express');
const bodyParser = require('body-parser');



//import route
const users = require('./route');

var app = express();


//Body parser middleware
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());


// Use routes
app.use('/users', users);



const port = process.env.PORT || 5000;

app.listen(port, () => console.log(`Server running on port ${port}`));

Server side route.js

const express = require('express');
const router = express.Router();

router.post('/create', (req,res) => {

    console.log(req.body);
    const user =
        {
            title: req.body.title ===null ? 'Untitled Note' : req.body.title,
            text: req.body.text
        };
    res.status(200).json(user);

});

module.exports = router;

Upvotes: 3

c-chavez
c-chavez

Reputation: 7496

You can use body-parser middleware to parse the body of your request

in your server.js:

const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json({limit: '10mb'}));

and supposing you send an object to the server like:

let data = {
    myProp: 'myVal1'
}

You can then get it in the request:

router.post('/create', (req,res,) => {
    let value = req.body.myProp;
    console.log('value in body: ' + value);
    // execute...
});

This will log:

value in body: myVal1

I would also strongly recommend using Axios for your requests instead of fetch, and read my answer in this post where I discuss some differences and how to implement axios if you are using fetch already. This way you don't need to stringify your data for example, and you solve other issues discussed there.

If you use Axios (with async/await), set your request object like so:

let reqObj = {
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json;charset=UTF-8'
    },
    url: 'http://localhost:3001/user/create',
    data:  {
        myProp: 'myVal1'
    }
};

And send the request to axios with:

let response = await axios(reqObj);

Upvotes: 0

You're sending a request to '/user/create' when your Node.js server is listening on 'create'. Try changing

fetch('http://localhost:3001/user/create'

to

fetch('http://localhost:3001/create'

Upvotes: 1

Related Questions