2017-06-27 104 views
0

我正在創建一個站點來顯示一些電話並設置了一個API以從我的數據庫中傳回最新的電話。在componentWillMount中的我的組件中,我調度一個動作,然後獲取API結果並填充我的商店。然後該組件呈現商店中的內容。Redux將初始狀態設置爲API響應

這似乎一切正常,但確實意味着有一段時間API調用正在進行時沒有任何顯示。

我想知道是否有某種方法來分派服務器上的操作,並將initialState設置爲API響應或其他方式將API響應從服務器傳遞到客戶端,以便數據組件已經呈現?

這是我迄今爲止...

減速

export function latestPhonesHasErrored(state = false, action) { 
    switch (action.type) { 
     case 'LATEST_PHONES_HAS_ERRORED': 
      return action.latestPhonesHasErrored; 
     default: 
      return state; 
    } 
} 

export function latestPhonesIsLoading(state = false, action) { 
    switch (action.type) { 
     case 'LATEST_PHONES_IS_LOADING': 
      return action.latestPhonesIsLoading; 
     default: 
      return state; 
    } 
} 

export function latestPhones(state = [], action) { 
    switch (action.type) { 
     case 'LATEST_PHONES_FETCH_DATA_SUCCESS': 
      return action.latestPhones; 
     default: 
      return state; 
    } 
} 

行動

export function latestPhonesFetchData() { 
    return (dispatch) => { 
     dispatch(latestPhonesIsLoading(true)); 

     fetch('/api/latest-phones/') 
      .then((response) => { 
       if (!response.ok) { 
        throw Error(response.statusText); 
       } 

       dispatch(latestPhonesIsLoading(false)); 

       return response; 
      }) 
      .then((response) => response.json()) 
      .then((results) => 
dispatch(latestPhonesFetchDataSuccess(results))) 
      .catch(() => dispatch(latestPhonesHasErrored(true))) 
    } 
} 

Server.js

const store = createStore(
    rootReducer, 
    initialState, 
    applyMiddleware(thunk) 
); 
const router = express.Router(); 

router.get('/', (req, res) => { 
     match({routes, location: req.originalUrl}, (err, redirectLocation, renderProps) => { 
      if(!err) { 
       const html = this.render(renderProps); 

       res.render('index', { 
        content: html, 
        pageTitle: 'title', 
        description: 'description', 
        canonical: 'canonical' 
       }); 
      } else { 
       res.status(500).send(); 
      } 
     }); 
    }); 

render(renderProps) { 
    let html = renderToString(
     <Provider store={store}> 
      <RouterContext {...renderProps}/> 
     </Provider> 
    ); 
    return html; 
} 

組件

import {latestPhonesFetchData} from '../../../actions/results-actions'; 

const mapStateToProps = (state) => { 
    return { 
     latestPhones: state.latestPhones 
    } 
}; 

class Home extends Component { 
    componentWillMount(){ 
     this.props.latestPhonesFetchData(); 
    } 

    render(){ 
     /* all component render here*/ 
    } 
} 
export default connect(mapStateToProps, {latestPhonesFetchData})(Home); 

任何幫助,非常感謝!

+1

因爲它是異步的,所以不能保證你可以在組件加載前擁有數據,你最好只是在加載數據時加載屏幕和更新加載屏幕。 –

+0

是的,我在我的網站上的其他地方做了這些,我有API請求,但我希望有一些方法可以在這種情況下通過正確的初始狀態,在這種情況下不需要用戶交互,以便Google也能夠爲搜索引擎優化目的抓取內容 – Phil

回答

1

如果您在客戶端(您是)渲染React,則無法在組件呈現前預加載數據。 @ A.Lau上面的評論是正確的......你最好的選擇是在獲取數據的同時呈現一個加載微調器或一些等價物。

或者,您可以使用服務器端呈現。這意味着提前渲染React並向客戶端提供HTML文件。通過在服務器上渲染,您可以從數據庫中獲取所需的數據,並在呈現之前將其作爲道具傳遞給組件。不需要AJAX,也不需要向客戶端顯示加載視圖。

+0

你有任何好的教程或服務器端渲染的例子,你推薦?我覺得這對我來說可能更有用,因爲我希望獲得內容加載的SEO優勢。 – Phil