我正在嘗試編寫一個簡單的測試react-redux應用程序來開始使用gmail API,現在狀態更改不會強制重新呈現。已連接的react-redux組件不會在狀態中重新提交
我做了什麼:
我讀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
這裏是顯示我的控制檯的屏幕截圖。 (我不是很瞭解這個跨框架的原點錯誤,並且會歡迎一個解釋,但我認爲這是我的問題的輔助,因爲我通過它併成功通過減速器傳遞行動。)
我成功在第一個渲染器的控制檯日誌標籤中,但是在狀態上設置標籤後沒有重新渲染,並且我不再控制日誌標籤(或渲染頁面上的標籤列表)。
感謝您提供任何幫助!
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))
})
}
我敢肯定你是對的,我沒有upvoted並接受你的答案的唯一原因是,現在由於某種原因連接到gmail api不工作,我沒有得到標籤更新因此我無法驗證您的建議是否可以解決任何問題。我試圖弄清楚什麼是錯誤的,以及更新我的問題還是提出一個新問題是否合適。 – Katie
是的,我不是那個api如何工作的。另外,如果您使用的是redux,則不需要本地狀態。也許一個解決問題的好方法是擺脫redux,並嘗試使其與反應組件中的本地狀態一起工作,然後將功能分解爲redux。 –
我修好了。我只需要調用fetchLabels()作爲.signIn()的關閉。我認爲之前沒有造成麻煩的唯一原因是我的登錄狀態持續存在於瀏覽器中,因此總有一位fetchLabel用戶可以找到。我會接受你的回答。謝謝你的幫助! – Katie