如何在我的商店/状态中删除商品后,如何在React与Redux中删除商品后我的视图更新
我是React和Redux的新手,刚开始习惯于管理状态和React。我前言说,因为我可能需要可能的解决方案来处理我所拥有的内容 - 基本上我会更好地理解它。 :)如何在我的商店/状态中删除商品后,如何在React与Redux中删除商品后我的视图更新
话虽这么说,这是我的问题:
我已经创造了反应,但有两个明显的问题,麻烦列表/表单组件。
虽然项目获取数据库中删除, 它仅仅体现在一旦刷新视图 您可能已经注意到列表#或在将项目从列表中删除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.setState(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>
);
}
}
StudentForm.js
import React, { Component } from "react";
import store from "../store";
import { postStudent } from "../reducers";
const blankFormState = {
name: "",
email: "",
campus: ""
};
export default class StudentForm extends Component {
constructor(props) {
super(props);
this.state = blankFormState;
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target;
this.setState({
[target.name]: target.value
});
}
handleSubmit(event) {
event.preventDefault();
store.dispatch(postStudent(this.state));
this.setState(blankFormState);
}
render() {
return (
<div className="container">
<div className="row">
<div className="twelve columns">
<form onSubmit={this.handleSubmit}>
<div className="row">
<div className="four columns">
<label>Name</label>
<input
className="u-full-width"
type="text"
name="name"
value={this.state.name}
onChange={this.handleChange}
/>
</div>
<div className="four columns">
<label>Email</label>
<input
className="u-full-width"
type="text"
name="email"
value={this.state.email}
onChange={this.handleChange}
/>
</div>
<div className="four columns">
<label>Campus</label>
<input
className="u-full-width"
type="text"
name="campus"
value={this.state.campus}
onChange={this.handleChange}
/>
</div>
</div>
<input className="button-primary" type="submit" />
</form>
</div>
</div>
</div>
);
}
}
我reducer.js
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);
newState = state.students.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;
这是我如何安装Students
和StudentForm
import React, { Component } from "react";
import Students from "./Students";
import StudentForm from "./StudentForm";
import store from "../store";
import { fetchStudents } from "../reducers";
export default class StudentContainer extends Component {
constructor(props) {
super(props);
this.state = store.getState();
}
componentDidMount() {
store.dispatch(fetchStudents());
this.unsubscribe = store.subscribe(() => this.setState(store.getState()));
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
return (
<div>
<Students students={this.state.students} />
<StudentForm />
</div>
);
}
}
我store.js
import { createStore, applyMiddleware } from "redux";
import rootReducer from "./reducers";
import createLogger from "redux-logger"; // https://github.com/evgenyrodionov/redux-logger
import thunkMiddleware from "redux-thunk"; // https://github.com/gaearon/redux-thunk
export default createStore(
rootReducer,
applyMiddleware(thunkMiddleware, createLogger())
);
删除学生你分派行动后,你是路过动作创建者scrubStudent
发送。您正在将该删除的学生的ID传递给该动作创建者。现在您已经定义了你的行动创造者的方式是这样的
export function scrubStudent(student) {
return {
type: DELETE_STUDENT,
student
};
}
所以这个函数的返回值将是一个对象是这样的
scrubStudent(5) // returns {type: "DELETE_STUDENT", student: 5}
但在你减速你是比较喜欢的ID这
case DELETE_STUDENT:
// console.log("action.student", action.student);
// console.log("state", state);
newState = state.students.filter(function(student) {
return student.id !== action.id;
});
return newState;
在上面的代码action.id
是未定义的。相反,学生ID保存为action.student
。所以比较将对数组的所有元素返回true。所以每次所有的元素都将被包含在新的状态中。因此,请尝试更改您的上述代码,如下所示:
case DELETE_STUDENT:
// console.log("action.student", action.student);
// console.log("state", state);
newState = state.students.filter(function(student) {
return student.id !== action.student;
});
return newState;
谢谢您的帮助。但是这个观点并没有更新。在做了一个'console.log('action.id',action.id)''我可以看到你是对的,我在那里比较'未定义'。但事后我意识到'action.student'上没有'id'属性那么我们为什么要比较呢? –
当你在后端结果返回后发送动作时,你正在传递学生的'id',从后端返回,如'return dispatch(scrubStudent(id));'。所以如果你的后端正在返回被删除的学生的id,那么'action.student'会包含这个id。 –
@ AntonioPavicevac-Ortiz另外我看到你正在使用store.getState()无处不在。我会推荐使用react-redux库[http://redux.js.org/docs/basics/UsageWithReact.html]。当你将组件连接到这个库时,只要你的状态改变,你的视图就会自动更新。 –
您能展示如何以及在哪儿安装'Students'? – Panther
@Panther,是的,如果我这样做会有帮助。我刚刚更新了它。 –
很酷。你也可以显示你的'store.js'吗? – Panther