2017-06-17 30 views
0

gmail APIを使用して作業を開始する簡単なテストリアクションレスキューアプリケーションを作成しようとしていますが、現在のところ状態の変更は再レンダリングを強制しません。私はを行っている何接続された反応還元コンポーネントは状態で再レンダリングしません。

を私はthis questionをお読みください。その人の問題は、connectがコンポーネントではないことに起因するように思われましたが、私が知っている限り、それをやっています。私はthis questionを読む。その人の問題は、誤解によって引き起こされましたcombineReducers状態でオブジェクトを設定しましたが、私はしません私は同じ誤解を持っています。私は別のものを持っていると確信しています!ここで

私のトップレベルのコンテナは、ルーティングと、次のとおりです。ここで

'use strict' 
import React from 'react' 
import {Router, Route, IndexRedirect, browserHistory} from 'react-router' 
import {render} from 'react-dom' 
import {connect, Provider} from 'react-redux' 

import store from './store' 
import Home from './components/Home' 
import Login from './components/Login' 
import WhoAmI from './components/WhoAmI' 
import NotFound from './components/NotFound' 
import { handleClientLoad } from './gmailApi' 

const ExampleApp = connect(
    ({ auth }) => ({ user: auth }) 
)(
    ({ user, children }) => 
    <div> 
     <nav> 
     {user ? <WhoAmI/> : <Login/>} 
     </nav> 
     {children} 
    </div> 
) 

const onAppEnter =() => { 
    handleClientLoad() 
} 

render(
    <Provider store={store}> 
    <Router history={browserHistory}> 
     <Route path="/" component={ExampleApp}> 
     <IndexRedirect to="/home" /> 
     <Route path="/home" component={Home} onEnter={onAppEnter} /> 
     </Route> 
     <Route path='*' component={NotFound} /> 
    </Router> 
    </Provider>, 
    document.getElementById('main') 
) 

は、コンポーネントをレンダリングするために私のコードです:ここでは

import React, { Component } from 'react' 
import { handleAuthClick, handleSignOutClick } from '../gmailApi' 
import store from '../store' 
import { connect } from 'react-redux' 


var authorizeButton = <button id="authorize-button" onClick={() => { handleAuthClick() }}>Authorize</button> 
var signOutButton = <button id="signout-button" onClick={handleSignOutClick}>Sign Out</button> 


const mapStateToProps = (state) => { 
    return { 
    labels: state.gmail.labels, 
    isSignedIn: state.gmail.isSignedIn 
    } 
} 

export const Labels = ({ isSignedIn, labels }) => { 
    var button = isSignedIn ? signOutButton : authorizeButton 
    console.log("labels ", labels) 
    return (
    <div> 
     {button} 
     <ul> 
     {labels && labels.map(label => <li>{label}</li>)} 
     </ul> 
    </div> 
) 
} 

export default class Home extends Component { 

    constructor(props) { 
    super(props) 

    this.state = {labels: [], isSignedIn: false} 
    } 

    render() { 
    return (
     <Labels labels={this.props.labels} isSignedIn={this.props.isSignedIn}/> 
    ) 
    } 

} 

connect(mapStateToProps)(Home) 

は私のGmailの減速やアクションクリエイターです:

let initialState = { 
    labels: [], 
    isSignedIn: false 
} 

const reducer = (state=initialState, action) => { 
    const newState = Object.assign({}, state); 
    switch (action.type) { 
    case SIGNED_IN: 
    newState.isSignedIn = action.isSignedIn 
    return newState 
    case RECEIVE_LABELS: 
    newState.labels = action.labels 
    return newState 
    } 

    return state 
} 

const SIGNED_IN = 'SIGNED_IN' 
export const signedIn = isSignedIn => ({ 
    type: SIGNED_IN, isSignedIn 
}) 


const RECEIVE_LABELS = 'LABELS' 
export const receiveLabels = labels => ({ 
    type: RECEIVE_LABELS, labels 
}) 


export default reducer 

ここに私はレジューサーを組み合わせています:

import { combineReducers } from 'redux' 

const rootReducer = combineReducers({ 
    auth: require('./auth').default, 
    gmail: require('./gmail').default 
}) 
export default rootReducer 

ここに私のコンソールを示すスクリーンショットがあります。 (私はこのクロスフレームの起点のエラーを本当に理解していないし、説明を歓迎するだろうが、私はそれを過ぎて、減速機を介してアクションを成功させるので、私の問題に付属していると仮定する)enter image description here

私は成功最初のレンダリングのコンソールロギングラベルでは、ラベルが状態に設定された後に再レンダリングが行われず、ログラベルを再度コンソール化しません(またはページ上のラベルのリストをレンダリングしません)。

ご協力いただきありがとうございます!

P.S.そして、完全性のために、ここで私は非同期のGmailのAPIのものをやっています。 (私は非同期アクションクリエイターのフォーマットに従っていないことを知っています.Gmail APIのサンプルコードを使って作業していますが、まずコードを実行してからコードを展開してクリーンアップしようとしています。 「Tは、状態が細かい読み込まれますので、問題はおそらくここにあることができると思います。私は、ページを再描画することはできません)

import store from '../store' 
import { signedIn, receiveLabels } from '../reducers/gmail' 
import gapi from './gapi' 
import '../store' 

var CLIENT_ID = '<stack overflow doesn't need to know this>'; 

// Array of API discovery doc URLs for APIs used by the quickstart 
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"]; 

// Authorization scopes required by the API; multiple scopes can be 
// included, separated by spaces. 
var SCOPES = "https://www.googleapis.com/auth/gmail.modify"; 


/** 
* On load, called to load the auth2 library and API client library. 
*/ 


export const handleClientLoad = function() { 
    gapi.load('client:auth2', initClient); 
} 

/** 
* Initializes the API client library and sets up sign-in state 
* listeners. 
*/ 
function initClient() { 
    gapi.client.init({ 
     discoveryDocs: DISCOVERY_DOCS, 
     clientId: CLIENT_ID, 
     scope: SCOPES 
    }).then(function() { 
     // Listen for sign-in state changes. 
     gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus) 

     // Handle the initial sign-in state. 
     updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get()); 


    }); 
} 

function updateSigninStatus(isSignedIn) { 

     console.log(isSignedIn) 
     store.dispatch(signedIn(isSignedIn)) 
} 

/** 
* Sign in the user upon button click. 
*/ 
export const handleAuthClick = function(event) { 
    console.log("got here") 
    gapi.auth2.getAuthInstance().signIn(); 
    fetchLabels() 
} 

/** 
* Sign out the user upon button click. 
*/ 
export const handleSignoutClick = function(event) { 
    gapi.auth2.getAuthInstance().signOut(); 
} 

/** 
* Append a pre element to the body containing the given message 
* as its text node. Used to display the results of the API call. 
* 
* @param {string} message Text to be placed in pre element. 
*/ 

/** 
* Print all Labels in the authorized user's inbox. If no labels 
* are found an appropriate message is printed. 
*/ 
function fetchLabels() { 
    console.log("gapi client ", gapi.client) 
    gapi.client.gmail.users.labels.list({ 
     'userId': 'me' 
    }).then(function (response) { 
     var labels = response.result.labels; 
     store.dispatch(receiveLabels(labels)) 
    }) 
} 

答えて

1

を私は見誤りは、あなたが接続されているコンポーネントを輸出していないということです。コンポーネントをエクスポートし、後で接続します。 connect関数は新しい高次コンポーネントを返します。コンポーネント自体には影響しません。また、connect関数は第2引数をとります。アクションクリエータはアクションをステートストアにディスパッチします。彼らはあなたのレデューサーに発砲したい場合は、それらのアクションをインポートする必要があります。

あなたは持っている:

export default class Home extends Component { 

    constructor(props) { 
    super(props) 

    this.state = {labels: [], isSignedIn: false} 
    } 

    render() { 
    return (
     <Labels labels={this.props.labels} isSignedIn={this.props.isSignedIn}/> 
    ) 
    } 

} 

connect(mapStateToProps)(Home) 

だけのように変更します。

import * as actions from './nameOfActionsFolder'; 

class Home extends Component { 

    constructor(props) { 
    super(props) 

    this.state = {labels: [], isSignedIn: false} 
    } 

    render() { 
    return (
     <Labels labels={this.props.labels} isSignedIn={this.props.isSignedIn}/> 
    ) 
    } 

} 

export default connect(mapStateToProps, actions)(Home); 

あなたが接続されているコンポーネントをエクスポートしますその方法を。

+0

私はあなたが正しいと確信しています。私はupvotedして答えを受け入れていない唯一の理由は、今何かgmail APIへの接続が機能していないと私はラベルが更新されませんあなたの提案が何かを修正することを確認することはできません。私は、何がうまくいかないのか、そして私の質問を更新したり、新しい質問をするのが適切かどうかを調べようとしています。 – Katie

+0

ええ、私はそのAPIの仕組みではありません。また、reduxを使用している場合は、ローカル状態は必要ありません。おそらく、トラブルシューティングの良い方法は、reduxを取り除き、それを反応コンポーネントの局所状態で動作させ、その機能を還元して還元することです。 –

+0

私はそれを修正しました。私はfetchLabels()を.signIn()の.thenとして呼び出す必要がありました。以前は問題が発生していない唯一の理由は、サインインした状態がブラウザに残っていたため、fetchLabelsのユーザーが常に見つかるということでした。私はあなたの答えを受け入れるでしょう。ご協力いただきありがとうございます! – Katie

関連する問題