Reactjs 如何从';反应';使用';Redux';
从本质上说,这个应用程序在保存到数据库的视图中显示了一个“学生”列表。现在,我希望能够删除一个学生,并使其保持不变。我相信答案就在组件本身 这是我到目前为止所做的,这是我的学生部分:Reactjs 如何从';反应';使用';Redux';,reactjs,react-redux,Reactjs,React Redux,从本质上说,这个应用程序在保存到数据库的视图中显示了一个“学生”列表。现在,我希望能够删除一个学生,并使其保持不变。我相信答案就在组件本身 这是我到目前为止所做的,这是我的学生部分: import React, { Component } from "react"; import store from "../store"; import { scrubStudent } from "../reducers"; export default class Students extends Com
import React, { Component } from "react";
import store from "../store";
import { scrubStudent } from "../reducers";
export default class Students extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.deleteStudent = this.deleteStudent.bind(this);
}
deleteStudent(itemIndex) {
console.log(this.state);
var students = this.state.students;
store.dispatch(scrubStudent(this.state));
students.splice(itemIndex, 1);
this.setState({
students: students
});
}
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={this.deleteStudent(index)}
>
<i className="fa fa-remove" />
</a>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
}
我要探究原因
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(function() {
this.setState(store.getState());
});
}
componentWillUnmount() {
this.unsubscribe();
}
deleteStudent(index) {
console.log(this.state);
var students = this.state.students;
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={() => this.deleteStudent(student.id)}
key={index}
>
<i className="fa fa-remove" />
</a>
</td>
</tr>
);
}, this)}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
}
应使用箭头函数,以便在映射函数中保留相关上下文:
{students.map((student, index) => {
这样,当您在函数中使用
This
时,它就是您当前的组件 下面的答案直接回答了出现错误的原因,但通过阅读代码,您缺少了Redux的一个基本点…**关注点分离**请参阅我的答案,了解一些相关信息@MatthewBrent事实上,当我测试此操作过程时,我达到了最大调用堆栈,在那里一切都出了问题!谢谢你的链接。@AntonioPavicevac Ortiz你检查我的答案了吗?你还有什么问题吗?@Dekel嘿,是的,我有!非常感谢。根据马修指出的,我还有一些其他的问题。我已经更新了我的问题,以反映到目前为止的进展情况!如果不知道上面代码中的第90行是哪一行,就很难帮上忙,但我的猜测是,这也是一个范围问题。当您使用function(){…}
时,您就失去了当前函数的作用域,这就是为什么我在回答中说您应该使用arrow函数的原因。
import { combineReducers } from "redux";
import axios from "axios";
// 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(function(students) {
return dispatch(getStudents(students));
})
.catch(function(err) {
return console.error(err);
});
};
}
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(function(err) {
return console.error(err);
});
};
}
export function deleteStudent(student) {
return function thunk(dispatch) {
return axios
.delete("/api/students/" + student.toString())
.then(function(res) {
return res.data;
})
.then(function(student) {
return dispatch(scrubStudent(student));
})
.catch(function(err) {
return console.error(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(function(err) {
return console.error(err);
});
};
}
export function postCampus(student) {
return function thunk(dispatch) {
return axios
.post("/api/campuses", campuse)
.then(function(res) {
return res.data;
})
.then(function(newCampus) {
return dispatch(getCampus(newCampus));
})
.catch(function(err) {
return console.error(err);
});
};
}
// 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:
newState.students = state.students.concat([action.student]);
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.map((student, index) => {