首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React缓存我的API请求

React缓存我的API请求
EN

Stack Overflow用户
提问于 2017-03-16 05:27:54
回答 1查看 4.7K关注 0票数 2

我有一个奇怪的问题,在我更新课程后,React似乎缓存了我的API GET请求。最近刚开始学习React,所以有很多新东西需要学习:)

进程:

首先,我去courseList.js,它列出了所有的课程。然后,我转到更新特定课程并重定向回courseList.js的courseUpdate.js

然而,在我更新课程后,我被重定向回courseList.js,它输出旧数据(在我更新之前)。我检查了我的API服务器,发现我的React应用程序在补丁(更新)之后没有发送任何请求。在我的控制台中,我还看到数据是陈旧的,但时间戳是最新的。此问题仅在我使用

代码语言:javascript
复制
this.props.router.push('/courses');
or
browserHistory.push({pathname: '/courses'});

当我使用

代码语言:javascript
复制
window.location.href = '/courses';

courseList.js按照预期加载新数据。

任何帮助或见解都将不胜感激。

谢谢!

courseList.js文件:

代码语言:javascript
复制
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>
    );
}

courseUpdate.js

代码语言:javascript
复制
getInitialState() {
    return {
      courses: {}
    };
},

componentDidMount() {
    fetchCourse(this.props.params.courseId)
      .then((data) => {
        this.setState(state => {
          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;
            return state;
          }

        })
      })
      .catch((err) => {
        console.error('err', err);
      });

    },
    handleSubmit(data) {
        updateCourse(this.state.courses.id, data);

        //TODO figure out why window.location redirect works, but router and browserhistory does not
        //this.props.router.push('/courses');
        window.location.href = '/courses';
        /*
        browserHistory.push({
            pathname: '/courses'
        });
        */
    },
    render() {
        return (
            <div>
                <CourseForm onSubmit={this.handleSubmit}
                    course_number={this.state.courses.course_number}
                    department={this.state.courses.department}
                />
            </div>
        );
    }

API调用:

代码语言:javascript
复制
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);
}
EN

回答 1

Stack Overflow用户

发布于 2017-03-16 05:58:46

乍一看,您使用的是(组件)本地状态,而您应该使用的是应用程序状态。

courseUpdate中的this.setState(...)不会更新courseList中的相应课程。这与单页应用程序相关,特别是当组件在导航过程中未被卸载时(例如,我在上面的评论中提到的)。

有两种方法可以完成此操作:

1- Lifting state up到共同的父级。这可能是解决这个问题的最简单的方法。下面是一个例子:

代码语言:javascript
复制
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>
        )
    }
}

在详细信息中,您可以调用props.updateItem,它将更新父对象中的项,并同步两个子对象( ListDetails),而不是更新那里的项。

2-我认为您正在寻找类似于redux (并且可能具有react-redux绑定)的东西。状态将由单个存储区管理,组件将一致地从中读取数据。如果它是一个大型应用程序,我会建议沿着这条路线走下去--如果你没有帮助,管理许多不同组件之间的共享状态可能会变得很麻烦。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42821010

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档