簡體   English   中英

如何在React組件/視圖中同步DOM和數據庫

[英]How to sync the DOM and Database in a React Component/View

我已經在React中創建了一個列表組件,但是遇到了兩個明顯的問題。

  1. 當項目被刪除(以及從數據庫中刪除)時,它僅在刷新時反映出來
  2. 您可能已經注意到列表#或從列表中刪除項目時ID列未減去。

我在后端使用PostgreSQL,並將Sequelize用作我的視圖/組件的對象/關系映射器和React。

我提供了一個gif,以便大家都能理解我的意思。

提前致謝!

這是我的代碼:

反應: Student.js

import React, { Component } from "react";
import store from "../store";
import { deleteStudent } from "../reducers";

export default class Students extends Component {
  constructor(props) {
    super(props);
    this.state = store.getState();
    this.deleteStudent = this.deleteStudent.bind(this);
  }

  componentDidMount() {
    this.unsubscribe = store.subscribe(() => {
      this.setState(store.getState());
    });
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  deleteStudent(index) {
    store.dispatch(deleteStudent(index));
    this.state = store.getState();
  }

  render() {
    var students = this.props.students;
    return (
      <div className="container">
        <div className="sixteen columns">
          <h1 className="remove-bottom">Students</h1>
          <h5>List of current students and their campus</h5>
          <hr />
        </div>
        <div className="sixteen columns">
          <div className="example">
            <div>
              <table className="u-full-width">
                <thead>
                  <tr>
                    <th>#</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Campus</th>
                  </tr>
                </thead>
                <tbody>
                  {students.map(function(student, index) {
                    return (
                      <tr key={index}>
                        <td>
                          {student.id}
                        </td>
                        <td>
                          {student.name}
                        </td>
                        <td>
                          {student.email}
                        </td>
                        <td>
                          {student.campus}
                        </td>
                        <td>
                          <a
                            className="button button-icon"
                            onClick={() => {
                              console.log(student.id);
                              this.deleteStudent(student.id);
                            }}
                            key={index}
                          >
                            <i className="fa fa-remove" />
                          </a>
                        </td>
                      </tr>
                    );
                  }, this)}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

我的減速機:

import { combineReducers } from "redux";
import axios from "axios";

const logError = console.error.bind(console);

// INITIAL STATE

const initialState = {
  students: [],
  campuses: []
};

//ACTION CREATORS

const UPDATE_NAME = "UPDATE_NAME";
const ADD_STUDENT = "ADD_STUDENT";
const DELETE_STUDENT = "DELETE_STUDENT";
const GET_STUDENTS = "GET_STUDENTS";
const UPDATE_CAMPUS = "UPDATE_CAMPUS";
const GET_CAMPUS = "GET_CAMPUS";
const GET_CAMPUSES = "GET_CAMPUSES";

// ACTION CREATORS

export function updateName(name) {
  const action = {
    type: UPDATE_NAME,
    name
  };
  return action;
}

export function addStudent(student) {
  return {
    type: ADD_STUDENT,
    student
  };
}

export function scrubStudent(student) {
  return {
    type: DELETE_STUDENT,
    student
  };
}

export function getStudents(students) {
  const action = {
    type: GET_STUDENTS,
    students
  };
  return action;
}

export function updateCampus(campus) {
  const action = {
    type: UPDATE_CAMPUS,
    campus
  };
  return action;
}

export function getCampus(campus) {
  const action = {
    type: GET_CAMPUS,
    campus
  };
  return action;
}

export function getCampuses(campuses) {
  const action = {
    type: GET_CAMPUSES,
    campuses
  };
  return action;
}

//THUNK CREATORS

export function fetchStudents() {
  return function thunk(dispatch) {
    return axios
      .get("/api/students")
      .then(function(res) {
        return res.data;
      })
      .then(students => {
        dispatch(getStudents(students));
      })
      .catch(logError);
  };
}

export function postStudent(student) {
  return function thunk(dispatch) {
    return axios
      .post("/api/students", student)
      .then(function(res) {
        return res.data;
      })
      .then(function(newStudent) {
        return dispatch(addStudent(newStudent));
      })
      .catch(logError);
  };
}

export function deleteStudent(id) {
  // console.log("student", student);
  return function thunk(dispatch) {
    return axios
      .delete("/api/students" + "/" + id)
      .then(function(id) {
        return dispatch(scrubStudent(id));
      })
      .catch(function(err) {
        return console.error("Removing student: " + id + " unsuccessful", err);
      });
  };
}

export function fetchCampuses() {
  return function thunk(dispatch) {
    return axios
      .get("/api/campuses")
      .then(function(res) {
        return res.data;
      })
      .then(function(campuses) {
        return dispatch(getCampuses(campuses));
      })
      .catch(logError);
  };
}

export function postCampus(student) {
  return function thunk(dispatch) {
    return axios
      .post("/api/campuses", campus)
      .then(function(res) {
        return res.data;
      })
      .then(function(newCampus) {
        return dispatch(getCampus(newCampus));
      })
      .catch(logError);
  };
}

// REDUCER

const rootReducer = function(state = initialState, action) {
  var newState = Object.assign({}, state);

  switch (action.type) {
    case GET_STUDENTS:
      newState.students = state.students.concat(action.students);
      return newState;

    case ADD_STUDENT:
      newState.students = state.students.concat([action.student]);
      return newState;

    case DELETE_STUDENT:
      console.log("action.student", action.student);
      console.log("state", state);
      state.filter(function(student) {
        return student.id !== action.id;
      });
      return newState;

    case GET_CAMPUSES:
      newState.campuses = state.campuses.concat(action.campuses);
      return newState;

    case GET_CAMPUS:
      newState.campuses = state.campuses.concat([action.campus]);
      return newState;

    default:
      return state;
  }
};

export default rootReducer;

這是我的學生模型:

'use strict';
var Sequelize = require('sequelize')
var db = require('../index.js')

//hasOne, hasMany, belongsTo, belongsToMany Sequelize methods

module.exports = db.define('student', {
  name: {
    type: Sequelize.STRING,
    allowNull: false,

  },

  email: {
    type: Sequelize.STRING,
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true
    }
  },

  campus: {
    type: Sequelize.STRING,
    allowNull: false,

  }
})

在此處輸入圖片說明

我想回答這個問題,但是您在此方面有很多不足。 我認為您需要將其放入GIT倉庫中,並以此方式獲得更多幫助。

您需要做的第一件事是創建正確的存儲配置/構建。 類似於以下內容...

import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import baseMiddleware from 'redux/middleware/'
import reducer from 'redux/modules/reducer'
import { routerMiddleware } from 'react-router-redux'
import { persistState } from 'redux-devtools';

export default function configureStore(initialState, history) {
    const middleware = baseMiddleware.with(thunk, createLogger(), routerMiddleware(history))

    const store = createStore(
        reducer,
        initialState,
        compose(
            applyMiddleware(...middleware),
            window.devToolsExtension ? window.devToolsExtension() : f => f,
            persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/))
        )
    )

    if (module.hot) {
        // Enable Webpack hot module replacement for reducers
        module.hot.accept('redux/modules/reducer', () => {
            const nextRootReducer = require('redux/modules/reducer').default
            store.replaceReducer(nextRootReducer)
        })
    }

    return store
}

這引用了兩個主要文件。 一個用於我的減速器,另一個用於我的中間件。 這很重要,因為它適合SOLID的S

這是我的中間件...

import api from './api'
import authenticationMiddleware from './authenticationMiddleware'
import analyticsMiddleware from './analyticsMiddleware'

const middleware = [ api, analyticsMiddleware, authenticationMiddleware ]

export default {
    with(){
        for(let i = 0; i < arguments.length; i++){
            middleware[middleware.length] = arguments[i];
        }

        return middleware
    },
    ...middleware
}

和減速器

import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';

import {reducer as form} from 'redux-form';

import authentication from './authentication'

const reducer = combineReducers({
    router: routerReducer,
    authentication
})

export default reducer

然后,您可以將商店傳遞到根組件中,並使用Provider高階組件將Redux上下文添加到對象圖中

import React, { Component, PropTypes } from 'react'
import { Provider } from 'react-redux'
import routes from '../routes'
import { Router } from 'react-router'

export default class Root extends Component {
  render() {
    const { store, history } = this.props
    return (
      <Provider store={store}>
        <div>
          <Router history={history} routes={routes} />
        </div>
      </Provider>
    )
  }
}

Root.propTypes = {
  store: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired
}

現在,如何將存儲傳遞到Root組件的方法更多,並且您選擇擁有歷史記錄,我將最后一部分交給您。

您還需要開始在組件上使用Connect函數來創建容器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM