简体   繁体   中英

Post data from form with Redux

Another newbie propblem. I want to post a post with my form. I have Post.js that looks like this:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import PostForm from './PostFormContainer';

export class Post extends Component {
  static propTypes = {
    posts: PropTypes.any,
    fetchPosts: PropTypes.func,
    sendPostData: PropTypes.func,
  };

  componentDidMount() {
    const { fetchPosts } = this.props;
    fetchPosts();
  }

  // onSubmit = (e, id, title, body) => {
  //   e.preventDefault();
  //   axios
  //     .post('https://jsonplaceholder.typicode.com/posts', {
  //       id,
  //       title,
  //       body,
  //     })
  //     .then(res =>
  //       this.setState({
  //         posts: [...this.state.posts, res.data],
  //       })
  //     );
  // };

  // onSubmit(e, id, title, body) {
  //   e.preventDefault();
  //   console.log('data');
  //   console.log('data', id);
  //   console.log('data', title);
  //   console.log('data', body);

  //   this.props.sendPostData(id, title, body);
  //   console.log('sendPostData', this.props.sendPostData(id, title, body));
  // }

  render() {
    console.log('props', this.props);
    const { posts } = this.props;
    if (!posts.length) {
      return (
        <div>
          <PostForm addPost={this.onSubmit} />
        </div>
      );
    } else {
      return (
        <div>
          <PostForm addPost={this.onSubmit} />
          <br />

          <div>
            {posts.map(post => (
              <div key={post.id}>
                <h3>{post.title}</h3>
                <p>{post.body}</p>
              </div>
            ))}
            ;
          </div>
        </div>
      );
    }
  }
}

export default Post;

Where I have <PostForm addPost={this.onSubmit} /> My PostForm.js looks like this:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class PostForm extends Component {
  ///state = {
   // title: '',
   // body: '',
  //};

  static propTypes = {
    posts: PropTypes.any,
    // fetchPosts: PropTypes.func,
    sendPostData: PropTypes.func,
  };

  //onChange = e => {
    //this.setState({
      // e.target.name zawsze będzie targetował pole z value i zmieniał jego stan
     // [e.target.name]: e.target.value,
   // });
  //};

  // onSubmit(e, id, title, body) {
  //   e.preventDefault();

  //   console.log('data');
  //   console.log('data', id);
  //   console.log('data', title);
  //   console.log('data', body);
  // }

  onSubmit(e, id, title, body) {
    e.preventDefault();
    console.log('data');
    console.log('data', id);
    console.log('data', title);
    console.log('data', body);
    // const post = {
    //   title,
    //   body,
    // };

    this.props.sendPostData(title, body);
    // console.log('sendPostData', this.props.sendPostData(post));
  }

  render() {
    console.log('props form', this.props);
    const { title, body } = this.props;
    return (
      <div>
        <h1> Add Post </h1>
        <form onSubmit={e => this.onSubmit(e, title, body)}>
          <div>
            <label>Title: </label>
            <input
              type='text'
              name='title'
              value={title}
              onChange={this.onChange}
            />
          </div>
          <div>
            <label>Body: </label>
            <textarea name='body' value={body} onChange={this.onChange} />
          </div>
          <button type='submit'>Submit</button>
        </form>
      </div>
    );
  }
}

export default PostForm;

Here I want to send this with my action. I have two container files PostFormContainer.js

import { connect } from 'react-redux';
import PostForm from './PostForm';
import { sendPost } from '../reducers/postReducers';

const mapStateToProps = state => ({
  posts: state.posts,
});

const mapDispatchToProps = dispatch => ({
  sendPostData: post => dispatch(sendPost(post)),
});

export default connect(mapStateToProps, mapDispatchToProps)(PostForm);

and PostContainer.js

import { connect } from 'react-redux';
import Post from './Post';
import { fetchFromApi } from '../reducers/postReducers';

const mapStateToProps = state => ({
  posts: state.posts,
});

const mapDispatchToProps = dispatch => ({
  fetchPosts: () => dispatch(fetchFromApi()),
  // sendPostData: (id, title, body) => dispatch(sendPost({ id, title, body })),
});

export default connect(mapStateToProps, mapDispatchToProps)(Post);

and my reducer

import Axios from 'axios';

const reducerName = 'posts';
const createActionName = name => `/${reducerName}/${name}`;

/* action type */

const FETCH_POSTS = createActionName('FETCH_POSTS');
const SUBMIT_POST = createActionName('SUBMIT_POST');

/* action creator */
export const fetchStarted = payload => ({ payload, type: FETCH_POSTS });
export const submitPost = payload => ({ payload, type: SUBMIT_POST });

/* thunk */
export const fetchFromApi = () => {
  return (dispatch, getState) => {
    Axios.get('https://jsonplaceholder.typicode.com/posts?_limit=5').then(
      res => dispatch(fetchStarted(res.data))
      // console.log('res', res)
      // console.log('res data', res.data)
    );
  };
};

export const sendPost = (postId, postTitle, postBody) => {
  return (dispatch, getState) => {
    Axios.post('https://jsonplaceholder.typicode.com/posts', {
      id: postId,
      title: postTitle,
      body: postBody,
    }).then(res => {
      dispatch(submitPost(res.data));
    });
  };
};

/* reducer */
export default function reducer(state = [], action = {}) {
  switch (action.type) {
    case FETCH_POSTS:
      return action.payload;
    case SUBMIT_POST: {
      return {
        ...state,
        data: action.payload,
      };
    }
    default:
      return state;
  }
}

Right now my console.logs shows that all my data is undefined. Not sure what the I am missing, but I can't solve this.

Here is also my stro.js

import { combineReducers, applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';

import postReducer from './reducers/postReducers';

const initialState = {
  posts: {
    data: {},
  },
};

const reducers = {
  posts: postReducer,
};

Object.keys(initialState).forEach(item => {
  if (typeof reducers[item] == 'undefined') {
    reducers[item] = (state = null) => state;
  }
});

const combinedReducers = combineReducers(reducers);

const store = createStore(
  combinedReducers,
  initialState,
  composeWithDevTools(applyMiddleware(thunk))
);

export default store;

Your PostForm element uses props title and body , but the place where you use PostForm doesn't send it a body or title prop.

I don't know your particular use case, but in React/Redux there are two ways to send a property to an element:

<PostForm body={this.state.postFormBody} title={this.state.postFormTitle} />

Or by using your Redux connector, mapStateToProps function, and returning an object with 'body' and 'title' keys that match something in your Redux store

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM