2017-03-15 11 views
2

コースを更新した後、ReactがAPI GET要求をキャッシュしているような、この奇妙な問題が起きています。私のAPI要求をキャッシュしているものを返す

まず、私はcourseList.jsに行き、すべてのコースを示しています。新しいものの多くは:)

プロセスを習得するためだけの学習では、最近REACT始めました。次にcourseUpdate.jsに行き、courseList.jsにリダイレクトします。

私はコースを更新した後、courseList.jsにリダイレクトされ、古いデータを出力します。更新)。私は自分のAPIサーバをチェックして、私のReactアプリがパッチ(更新)後にリクエストを送信していないことを確認します。私のコンソールでは、データは古くなっていますが、タイムスタンプは現在のものです。予想通り、私は

window.location.href = '/courses'; 

courseList.js負荷新鮮なデータを使用する場合、私は

this.props.router.push('/courses'); 
or 
browserHistory.push({pathname: '/courses'}); 

を使用する場合この問題は発生しています。

ご不明な点がありましたら、お気軽にお問い合わせください。

ありがとうございます!

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> 
    ); 
} 

courseUpdate.js

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コール:あなたは(コンポーネント)を使用しているように一見

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); 
} 
+1

'CourseList'と' CourseUpdate'は同時に表示されています(マスターディテールレイアウトですか?)そうであれば、 "away from"をナビゲートすると 'componentDidMount'は再び呼び出されません。ブラウザのナビゲーションイベント) 'courseUpdate' –

答えて

3

、それが見えますアプリ状態を使用する必要があるローカル状態。

this.setState(...)courseUpdatecourseListの対応するコースは更新されません。これは、単一ページアプリケーションに関係します。特に、コンポーネントがナビゲーション中にアンロードされていない場合(たとえば、上記のコメントで言及したような)共通の親へLifting state up -

1:

はこれを行うには2つの方法があります。これはおそらくこの問題を解決する最も簡単な方法です。例は次のようになります。詳しく内

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を呼び出し、2人の子供(ListDetails両方)を同期すると思います。

2 - あなたはredux(おそらくreact-reduxバインディング)のようなものを探していると思います。状態は単一のストアによって管理され、コンポーネントは一貫してそこから読み取られます。大規模なアプリケーションになる場合は、このルートを踏むことをお勧めします。ヘルプがなければ、さまざまなコンポーネント間の共有状態を管理することで毛が出ることがあります。

関連する問題