Javascript [SOLVED]: How to post data to an API server using axios library in redux

Javascript [SOLVED]: How to post data to an API server using axios library in redux

Home Forums Scripting Javascript Tutorials Javascript [SOLVED]: How to post data to an API server using axios library in redux

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #245706

    Cloudy Point
    Keymaster

    QuestionQuestion

    I have a redux form from which I am retrieving data and trying to post it to my API server.The code for my redux-form is given below:

    import React, { Component } from 'react';
    import { Field, reduxForm } from 'redux-form';
    import { Link } from 'react-router-dom';
    import { connect } from 'react-redux';
    import { createPosts } from '../actions/posts_action';
    
    class CreatePost extends Component {
      constructor() {
        super();
        this.state = {
          selectValue : ''
      };
       this.renderCategory = this.renderCategory.bind(this);
    }
    
      renderField(field) {
          return(
            <div className="title-design">
                <label className="label-design"> {field.label} </label>
                <input
                  type="text"
                  className="title-input"
                  {...field.input}
                />
                <div className="text-help  has-danger">
                  {field.meta.touched ? field.meta.error : ''}
                </div>
          </div>
          );
      }
    
    
      renderCategory(field) {
        return(
          <div className="title-design">
            <label className="label-design">{field.label} </label>
              <Field name="category" className="title-input" component="select">
                <option></option>
                <option value="react">React</option>
                <option value="redux">Redux</option>
                <option value="udacity">Udacity</option>
              </Field>
    
              <div className="text-help has-danger">
                {field.meta.touched ? field.meta.error : ''}
              </div>
          </div>
        );
      }
    
        onSubmit(values) {
          this.props.createPosts(values, () => {
              this.props.history.push('/');
          });
        }
    
    
    
        render() {
          const { handleSubmit } = this.props;
    
          return (
            <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
              <Field
                label="Title for Post"
                name="title"
                component={this.renderField}
              />
    
              <Field
                label="Post Content"
                name="body"
                component={this.renderField}
              />
    
              <Field
                label="Category"
                name="category"
                component={this.renderCategory}
                />
    
              <button type="submit" className="btn btn-primary">Submit</button>
              <Link  to="/">
                <button className="cancel-button">Cancel</button>
              </Link>
            </form>
          );
        }
    }
    
    function validate(values) {
      const errors = {} ;
    
      if (!values.title) {
          errors.title = "Enter a title";
      }
    
      if (!values.body) {
        errors.body = "Enter some content";
        }
    
      if(!values.category) {
        errors.category = "Please select a category";
      }
      return errors;
    }
    
    export default reduxForm({
      validate : validate,          //validate
      form : 'CreatePostForm'
    })(
      connect(null,{ createPosts })(CreatePost)
    );
    

    My Action creator for posting data to the API server is:

    //Action Creator for creating posts
    export function createPosts(values, callback) {
      const request = axios.post(`${API}/posts`,values,{headers})
        .then(() => callback());
        console.log(request);    
      return dispatch => {
        return request.then(({data}) => {
          dispatch({
            type: CREATE_POST,
            payload: data
          })
        })
      }
    }
    

    My reducer for creating the post is:

    import _ from 'lodash';
    import { FETCH_POSTS, FETCH_POST, CREATE_POST } from '../actions/posts_action';
    
    export default function(state = {}, action) {
      switch (action.type) {
        case FETCH_POST:
          // const post = action.payload.data;
          // const newState  = { ...state,  };
          // newState[post.id] = post;
          // return newState;
          return {...state, [action.payload.id]: action.payload};
    
        case FETCH_POSTS:
         return {posts: { ...state.posts, ...action.payload }};
    
        case CREATE_POST:
          return {posts: { ...state, ...action.payload}};
    
         default:
          return state;
      }
    
    }
    

    My index file for all the reducers combined together is:

    import { combineReducers } from 'redux';
    import PostReducer from './PostsReducer';
    import { reducer as formReducer} from 'redux-form';
    import CategoriesReducer from './CategoriesReducer';
    
    const rootReducer = combineReducers({
        posts: PostReducer,
        categories: CategoriesReducer,
        form : formReducer
    });
    
    export default rootReducer;
    

    Now the issue I am facing is,when I try to submit my form data, I get the error as shown in the screenshot below:

    error_file

    Can anyone please guide me with what I am doing wrong and how to proceed?

    EDIT 1 Code index.js file for the whole project is given below:

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Provider } from 'react-redux';
    import { createStore, applyMiddleware } from 'redux';
    import { BrowserRouter, Route } from 'react-router-dom';
    import thunk from 'redux-thunk';
    import './index.css';
    import App from './App';
    import reducers from './reducers/index.js'
    import Posts from './components/posts_index';
    import CreatePost from './components/new_post';
    import PostDetail from './components/post_detail';
    import CategoryView from './components/category';
    import { compose } from 'redux';
    
    //const createStoreWithMiddleware = createStore(reducers,applyMiddleware(thunk));
    
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
     const createStoreWithMiddleware = createStore(reducers, composeEnhancers(applyMiddleware(thunk)));
    
    ReactDOM.render(
      <Provider store={createStoreWithMiddleware}>
          <BrowserRouter>
            <div>
              <Route  path="/new" component={CreatePost} />
              <Route path="/posts/:id" component={PostDetail} />
              <Route exact  path="/" component={Posts} />
              <Route path="/:category/posts" component={CategoryView} />
            </div>
          </BrowserRouter>
      </Provider>  , document.getElementById('root'));
    

    Edit 2:

    I am also adding the file for the API server below:

    const clone = require('clone')
    
    let db = {}
    
    const defaultData = {
      "8xf0y6ziyjabvozdd253nd": {
        id: '8xf0y6ziyjabvozdd253nd',
        timestamp: 1467166872634,
        title: 'Udacity is the best place to learn React',
        body: 'Everyone says so after all.',
        author: 'thingtwo',
        category: 'react',
        voteScore: 6,
        deleted: false,
        commentCount: 2
      },
      "6ni6ok3ym7mf1p33lnez": {
        id: '6ni6ok3ym7mf1p33lnez',
        timestamp: 1468479767190,
        title: 'Learn Redux in 10 minutes!',
        body: 'Just kidding. It takes more than 10 minutes to learn technology.',
        author: 'thingone',
        category: 'redux',
        voteScore: -5,
        deleted: false,
        commentCount: 0
      }
    }
    
    function getData (token) {
      let data = db[token]
      if (data == null) {
        data = db[token] = clone(defaultData)
      }
      return data
    }
    
    function getByCategory (token, category) {
      return new Promise((res) => {
        let posts = getData(token)
        let keys = Object.keys(posts)
        let filtered_keys = keys.filter(key => posts[key].category === category && !posts[key].deleted)
        res(filtered_keys.map(key => posts[key]))
      })
    }
    
    function get (token, id) {
      return new Promise((res) => {
        const posts = getData(token)
        res(
          posts[id].deleted
            ? {}
            : posts[id]
        )
      })
    }
    
    function getAll (token) {
      return new Promise((res) => {
        const posts = getData(token)
        let keys = Object.keys(posts)
        let filtered_keys = keys.filter(key => !posts[key].deleted)
        res(filtered_keys.map(key => posts[key]))
      })
    }
    
    function add (token, post) {
      return new Promise((res) => {
        let posts = getData(token)
    
        posts[post.id] = {
          id: post.id,
          timestamp: post.timestamp,
          title: post.title,
          body: post.body,
          author: post.author,
          category: post.category,
          voteScore: 1,
          deleted: false,
          commentCount: 0
        }
    
        res(posts[post.id])
      })
    }
    
    function vote (token, id, option) {
      return new Promise((res) => {
        let posts = getData(token)
        post = posts[id]
        switch(option) {
            case "upVote":
                post.voteScore = post.voteScore + 1
                break
            case "downVote":
                post.voteScore = post.voteScore - 1
                break
            default:
                console.log(`posts.vote received incorrect parameter: ${option}`)
        }
        res(post)
      })
    }
    
    function disable (token, id) {
        return new Promise((res) => {
          let posts = getData(token)
          posts[id].deleted = true
          res(posts[id])
        })
    }
    
    function edit (token, id, post) {
        return new Promise((res) => {
            let posts = getData(token)
            for (prop in post) {
                posts[id][prop] = post[prop]
            }
            res(posts[id])
        })
    }
    
    function incrementCommentCounter(token, id, count) {
      const data = getData(token)
      if (data[id]) {
        data[id].commentCount += count
      }
    }
    
    module.exports = {
      get,
      getAll,
      getByCategory,
      add,
      vote,
      disable,
      edit,
      getAll,
      incrementCommentCounter
    }
    

    #245707

    Cloudy Point
    Keymaster

    Accepted AnswerAnswer

    Update: Try this format for the action creator. :

    export function createPosts(values, callback) {
    
      return dispatch => { //return function
        return axios.post(`${API}/posts`,values,{headers}) //return post request response
        .then((data) => { //pass data in as a parameter, call the callback, dispatch the action. 
            callback();
    
          dispatch({
            type: CREATE_POST,
            payload: data
          })
        })
      }
    }
    

    Source: https://stackoverflow.com/questions/48030335/how-to-post-data-to-an-api-server-using-axios-library-in-redux
    Author: Dream_Cap
    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.