Reactjs 响应缓存我的API请求
我遇到了一个奇怪的问题,React似乎在更新课程后缓存我的API GET请求。最近刚开始学习,有很多新东西需要学习:) 过程: 首先,我转到courseList.js,它列出了所有课程。然后,我转到courseUpdate.js,它更新特定的课程并重定向回courseList.js 但是,更新课程后,我会被重定向回courseList.js,它会输出旧数据(在更新之前)。我检查了我的API服务器,发现我的React应用程序在补丁(更新)后没有发送任何请求。在我的控制台中,我还看到数据是过时的,但时间戳是当前的。此问题仅在我使用时发生Reactjs 响应缓存我的API请求,reactjs,react-router,isomorphic-fetch-api,Reactjs,React Router,Isomorphic Fetch Api,我遇到了一个奇怪的问题,React似乎在更新课程后缓存我的API GET请求。最近刚开始学习,有很多新东西需要学习:) 过程: 首先,我转到courseList.js,它列出了所有课程。然后,我转到courseUpdate.js,它更新特定的课程并重定向回courseList.js 但是,更新课程后,我会被重定向回courseList.js,它会输出旧数据(在更新之前)。我检查了我的API服务器,发现我的React应用程序在补丁(更新)后没有发送任何请求。在我的控制台中,我还看到数据是过时的,但
this.props.router.push('/courses');
or
browserHistory.push({pathname: '/courses'});
当我使用
window.location.href = '/courses';
js按预期加载新数据
如有任何帮助或见解,将不胜感激
谢谢
courseList.js文件:
constructor(props) {
super(props);
this.state = {
courses: [],
loading: true
};
console.log("Current token: "+sessionStorage.getItem('access_token'));
console.log("Expires: "+sessionStorage.getItem('access_token_expires'));
}
componentDidMount() {
fetchCourses()
.then((data) => {
this.setState(state => {
console.log(new Date().toLocaleString());
console.log(data);
if(data["error"] === "invalid_grant"){
console.log("token expired...redirecting to login");
//TODO try to get new token without user redirect
this.props.router.push('/login');
}else{
state.courses = data;
state.loading = false;
return state;
}
})
})
.catch((err) => {
console.error('err', err);
});
}
render() {
let loading = this.state.loading ? 'loading' : 'loaded';
return (
<div>
<h1>Course list</h1>
<table className={"table table-hover table-responsive text-center " +loading}>
<thead>
<tr>
<th className="text-center">id</th>
<th className="text-center">Department</th>
<th className="text-center">Course Number</th>
<th className="text-center">Edit</th>
</tr>
</thead>
<tbody>
{this.state.courses && this.state.courses.map((post, i ) => {
return (
<tr key={post.id}>
<td>{post.id}</td>
<td>{post.department}</td>
<td>{post.course_number}</td>
<td>
<Link to={`/courses/${post.id}`} className="btn btn-default btn-sm">Edit</Link>
<btn onClick={this.deleteHandler.bind(this, post.id)} className="btn btn-danger btn-sm">Delete</btn>
</td>
<td>
</td>
</tr>
);
})}
</tbody>
</table>
<Link to={`/courses/create`} className="btn btn-default btn-sm">Create course</Link>
<br/>
<small>Page generated on: {new Date().toLocaleString()}</small>
</div>
);
}
乍一看,您似乎正在使用(组件)本地状态,而您应该使用应用程序状态
课程更新中的此.setState(…)
不会更新课程列表中的相应课程。这与单页应用程序相关,尤其是在导航期间未卸载组件时(例如,我在上面的评论中提到的组件)
有两种方法可以做到这一点:
1-给一个共同的父母。这可能是解决这个问题最简单的方法。例如:
class ContainerComponent {
updateItem = (item, newData) => {
updateTheItem(item, newData).then((updatedItem) => {
/* replace the item in state with updatedItem */
});
}
componentDidMount() {
fetchItems().then(/* store items in state */);
}
render() {
const { items } = this.state;
return (
<div>
<List items={ items } onItemSelect={(item) => this.setState({ selectedItem: item })}>
<Detail item={ this.state.selectedItem } updateItem={ this.updateItem }>
</div>
)
}
}
class集装箱组件{
updateItem=(项目,新数据)=>{
updateItem(item,newData)。然后((updateItem)=>{
/*将状态为的项替换为UpdateItem*/
});
}
componentDidMount(){
fetchItems()。然后(/*以状态*/)存储项;
}
render(){
const{items}=this.state;
返回(
this.setState({selectedItem:item})}>
)
}
}
在detail中,您可以调用props.updateItem
,而不是更新那里的项目,这将在父级中更新它,并同步两个子级(都是List
和Details
)
2-我认为您正在寻找类似于redux
(可能还有react redux
绑定)的东西。状态将由单个存储管理,并且组件将一致地从中读取。如果它将是一个大型应用程序,我建议沿着这条路线走——如果没有帮助,管理许多不同组件之间的共享状态可能会变得棘手 CourseList
和CourseUpdate
是否同时显示(即在主详细布局中?)如果是这样,当您导航到“远离”(react router链接不会在浏览器中引起导航事件)时,不会再次调用componentDidMount
export function fetchCourses() {
console.log("Fetching courses");
return fetch(Config.apiBaseUrl+'/courses', {
method: 'GET',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+auth.getToken(),
},
cache: 'no-cache'
}).then(res => res.json())
.catch(err => err);
}
export function updateCourse(id, data){
return fetch(Config.apiBaseUrl+'/courses/'+id, {
method: 'PATCH',
mode: 'cors',
body: JSON.stringify(data),
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer '+auth.getToken(),
'Content-Type' : 'application/json'
}
}).then(res => {
return res;
}).catch(err => err);
}
class ContainerComponent {
updateItem = (item, newData) => {
updateTheItem(item, newData).then((updatedItem) => {
/* replace the item in state with updatedItem */
});
}
componentDidMount() {
fetchItems().then(/* store items in state */);
}
render() {
const { items } = this.state;
return (
<div>
<List items={ items } onItemSelect={(item) => this.setState({ selectedItem: item })}>
<Detail item={ this.state.selectedItem } updateItem={ this.updateItem }>
</div>
)
}
}