简体   繁体   中英

Save and Edit post in reactjs and redux

I've been trying to create a blog like website where user can add new post, save them and edit them later. I'm making this website in reactjs and redux. I've few confusions as to how to edit the post, like how will my website know that the user has clicked on this certain post to edit. To do I've used link from react router with the id at the end of the url but I'm not sure if it's the right way to do. Also, when I open the editor page of an existing post, it should load as it was last saved, ie both the title input and the textarea should already be loaded with text when a user clicks on an already existing posts from the homepage.

I've created a codesandbox of the website. I'm not sure why all the lines in the switch statements in the reducer file is underlined with red.

this is my home.js file where the snippets will load

import React from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { onLoad, setEdit } from "./actions/posts";
import { connect } from "react-redux";

class Home extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    //Load all the snippets
    onLoad();
  }

  render() {
    const { snippets } = this.props;

    return (
      <div className="container">
        <div className="row pt-5">
          <div className="col-12 col-lg-6 offset-lg-3">
            <h1 className="text-center">Snippets</h1>
          </div>
        </div>
        <div className="row pt-5">
          <div className="col-12 col-lg-6 offset-lg-3">
            {snippets.map(snippet => {
              return (
                <div className="card my-3" key={snippet.snippetData.snippetId}>
                  <div className="card-header">{snippet.title}</div>
                  <div className="card-body">{snippet.snippetDescription}</div>
                  <div className="card-footer">
                    <div className="row">
                      <button
                        // onClick={() => this.handleEdit(snippet)}
                        className="btn btn-primary mx-3"
                      >
                        <Link to={`/editor/:${snippet.snippetData.snippetId}`}>
                          Edit
                        </Link>
                      </button>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </div>
    );
  }
}

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

export default connect(
  mapStateToProps,
  { onLoad, setEdit }
)(Home);

editor.js page

import React, { Component } from "react";
import { connect } from "react-redux";
import { savePost, retrievePost } from "./actions/posts";

class Editor extends Component {
  state = {
    title: "",
    enteredText: ""
  };
  componentDidMount() {
    //Load the snippet
    retrievePost(); // will it load the snippetId too?
  }

  handleChange = event => {
    const { value } = event.target;
    this.setState({
      enteredText: value
    });
  };

  // Save Snippet
  performSave = snippetData => {
    const { enteredText, title } = this.state;
    savePost(snippetData.snippetId, enteredText, title); //is it the right way to send the parameters to save the post??
  };

  render() {
    return (
      <>
        <input
          type="text"
          id="titletext"
          placeholder="Enter title here"
          limit-to="64"
          className="inptxt"
          onChange={title => this.setState({ title })}
        />
        <button
          className="btn savebtn"
          onClick={() => this.handlePost({ ...this.state })}
        >
          Save Snippet
          <i className="fas fa-save" />
        </button>

        <div
          contentEditable={true}
          spellCheck="false"
          name="enteredText"
          placeholder="Enter your text here"
          onChange={this.handleChange}
        />
      </>
    );
  }
}

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

export default connect(
  mapStateToProps,
  { savePost, retrievePost }
)(Editor);

actions.js file

import { SAVE_POST, UPDATE_POST, RETRIEVE_POST, HOME_LOADED } from "./types";

export const savePost = ({
  snippetId,
  snippetDescription,
  snippetTitle
}) => async dispatch => {
  const config = {
    headers: {
      "Content-Type": "application/json"
    }
  };
  let snippetData = { snippetId, snippetDescription, snippetTitle };
  try {
    if (snippetId == null) {
      const res = await axios.post(
        "/api/save",
        JSON.stringify(snippetData),
        config
      );
      snippetData.snippetId = res.data;
      dispatch({
        type: SAVE_POST,
        payload: snippetData
      });
    } else {
      const res = await axios.post(
        "/api/update",
        JSON.stringify(snippetData),
        config
      );
      dispatch({
        type: UPDATE_POST,
        payload: snippetData
      });
    }
  } catch (err) {
    console.log(err);
  }
};

// Retrieve post

export const retrievePost = snippetId => async dispatch => {
  try {
    const res = await axios.post(`/api/snippetdata/${id}`);
    dispatch({
      type: RETRIEVE_POST,
      payload: res.data
    });
  } catch (err) {
    console.error(err);
  }
};

//Retrieve all the post
export const onLoad = () => async dispatch => {
  try {
    const res = await axios.post(`/api/mysnippets/`);
    dispatch({
      type: HOME_LOADED,
      payload: res.data
    });
  } catch (err) {
    console.error(err);
  }
};

// edit a post

First, I have fixed some problems for you:

https://codesandbox.io/s/amazing-bird-dd2mb

I did not fix the editor page, cuz I give up, it is meaningless to give you a working code while learning nothing.

I suggest you stop playing react now, you do not have enough experience to use a complex framework.

What problem your code has:

  1. Wrongly import a commonJS module
  2. Misuse combineReducers
  3. Misuse html form element
  4. Misuse js switch
  5. Do not understand redux state correctly
  6. Do not understand reducer fully
  7. Do not have basic debuging skills ...

STOP WRITING CODE THAT YOU DO NOT UNDERSTAND

This project is too complex for a beginner.

I suggest you:

  1. Implement a counter in vanilla js
  2. Implement a todo list in vanilla js
  3. RE-implement the counter with pure react, no redux, no react-router
  4. RE-implement the counter with react + redux
  5. RE-implement the counter with react + redux + thunk
  6. RE-implement the counter with react + redux + saga

Repeat 3-6 but a todo list.

Then try to code a blog.

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