2016-11-21 4 views
2

При загрузке страницы, я отправляю внутри своего index.js, действие store.dispatch(getWeatherReports());, которое попадает в API погоды. Это действие проходит через процесс redux и в итоге добавляет данные, возвращенные в свойство, в состоянии, которое называется weatherReports. Это свойство представляет собой объект с пустым массивом. Теперь я собираюсь вставить обзор кода. Не все это, чтобы избавить вас от необходимости переходить к строке, поскольку вывод данных из API НЕ является проблемой, с которой я сталкиваюсь.Компонент визуализации после отправки действия

Вот мой index.js:

import 'babel-polyfill'; 
import React from 'react'; 
import {render} from 'react-dom'; 
import configureStore from './store/configureStore'; 
import {Provider} from 'react-redux'; 
import {Router, browserHistory} from 'react-router'; 
import {StyleRoot} from 'radium'; 
import routes from './routes'; 
import {loadBlogs} from './actions/blogActions'; 
import {loadUsers, getActiveUser} from './actions/userActions'; 
import {getWeatherReports} from './actions/weatherActions'; 
import '../node_modules/bootstrap/dist/css/bootstrap.min.css'; 
import '../node_modules/toastr/build/toastr.min.css'; 
import './styles/app.scss'; 

const store = configureStore(); 
store.dispatch(loadBlogs()); 
store.dispatch(loadUsers()); 
store.dispatch(getActiveUser()); 
store.dispatch(getWeatherReports()); 

render(
    <StyleRoot> 
    <Provider store={store}> 
     <Router history={browserHistory} routes={routes}/> 
    </Provider> 
    </StyleRoot>, 
    document.getElementById('app') 
); 

траст, что это проходит через правильный процесс, чтобы вернуть данные. Затем я создал компонент smart, который принимает это состояние и, похоже, передает его в немой компонент.

class DashboardPage extends React.Component { 
    constructor(props, context) { 
    super(props, context); 

    this.state = { 
     weatherReports: [] 
    }; 

    } 

    <ContentBox 
    title="What The Wind Blew In" 
    content={<WeatherReport reports={this.props.weatherReports} /> 
    /> 

Опять же, доверие, что я правильно mapStateToProps, mapDispatchToProps и т.д. Затем я смотрю, чтобы отобразить данные в dumb компоненте. WeatherReport.js:

import React, {PropTypes} from 'react'; 
import styles from '../common/contentBoxStyles'; 

const WeatherReport = ({reports}) => { 
    console.log(reports); 
    return (
     <div style={styles.body} className="row"> 
      <div style={styles.weatherBoxContainer}> 
       <div className="col-sm-2 col-md-offset-1" style={styles.weatherBoxContainer.weatherCard}> 
        <div style={styles.weatherBoxContainer.weatherReport}> 
         <div style={styles.weatherBoxContainer.currentTemp}> 
          HERE IS MY PROBLEM!! 
          {reports[0].main.temp} 
         </div> 
        </div> 
        CA 
       </div> 
       <div className="col-sm-2" style={styles.weatherBoxContainer.weatherCard}> 
        <div style={styles.weatherBoxContainer.weatherReport}> 
         Report 
        </div> 
        UT 
       </div> 
       <div className="col-sm-2" style={styles.weatherBoxContainer.weatherCard}> 
        <div style={styles.weatherBoxContainer.weatherReport}> 
         Report 
        </div> 
        MN 
       </div> 
       <div className="col-sm-2" style={styles.weatherBoxContainer.weatherCard}> 
        <div style={styles.weatherBoxContainer.weatherReport}> 
         Report 
        </div> 
        DC 
       </div> 
       <div className="col-sm-2" style={styles.weatherBoxContainer.weatherCard}> 
        <div style={styles.weatherBoxContainer.weatherReport}> 
         Report 
        </div> 
        NY 
       </div> 
      </div> 
     </div> 
    ); 
}; 

WeatherReport.propTypes = { 
    reports: PropTypes.array 
}; 

export default WeatherReport; 

Мой основной вопрос заключается в том, что перед моим диспетчерским действием возвращает данные .. Я пытаюсь сделать это через мой dumb компонента. Таким образом, я получаю следующую ошибку при попытке доступа к данным: Uncaught TypeError: Cannot read property 'main' of undefined(…) при выполнении следующих действий: reports[0].main.temp Что происходит, так это то, что это прекращается, когда мое приложение перемещается вперед, так что store.dispatch(getWeatherReports()); никогда не вызывается. Таким образом, если я удалю {reports[0].main.temp} из уравнения, то процесс продолжится и действие будет отправлено. Тогда я могу назвать уравнение w/HMR и hooray !! Данные есть ...

Итак, мой вопрос и благодарность за то, что он со мной связан, заключается в том, как я могу его получить, чтобы мой немой компонент ожидал, чтобы попытаться получить доступ к этим свойствам в состоянии до тех пор, пока ПОСЛЕ моих начальных отправленных действий не произойдет ?

ответ

1

Проверить, существует ли reports[0], прежде чем пытаться получить доступ к .main. Если это undefined затем отобразить загрузочное блесну или что-то ...

if (!reports[0]) return <div>Loading...</div> 

return (
    // your component like normal. 
) 
1

Если запрос getWeatherReports делается на то, что поддерживает обещания, а не обратные вызовы, чтобы уведомить вас об успешном ответе (то есть что-то вроде axios), то вы можете попробовать использовать промежуточное программное обеспечение, например redux-prom.

Что делать redux-prom будет перехватывать действие отправки и не позволяет ему перенаправлять действие подписчикам магазина, если обещание не было разрешено.

Как только вы получите успешный ответ и обещание будет разрешено, промежуточное ПО создает новое действие с тем же типом действия, что и оригинал, но с полезной нагрузкой, содержащей нужные вам данные.

Вы бы использовать его следующим образом:

import { createStore, applyMiddleware } from 'redux'; 
import promise from 'redux-promise'; 

const store = configureStore(); 
store.dispatch(loadBlogs()); 
... 
... 
store.dispatch(getWeatherReports()); 

const storeWithMiddleWare = applyMiddleware(promise)(store); 
1

Похоже store.dispatch(getWeatherReports()) асинхронный вызов API. Поэтому вам нужно дождаться ответа, прежде чем отображать свой компонент в DOM.

Решение: использовать redux-connect.

Ключевых моментов:

  • Это позволяет запрашивать данные асинхронных, хранить их в Redux состояния и подключить их к вашей реакции компоненты.

  • Этот пакет состоит из 2-х частей: одна часть позволяет задержки контейнеров рендеринга до тех пор, некоторые действия асинхронных не происходит. Другой хранит ваши данные в состоянии redux и подключит ваши загруженные данные к вашему контейнеру.

Ваш компонент не будет оказывать, пока обещание не будет выполнено.

Основными преимуществами являются:

  • Простой и элегантный, чтобы настроить как для CSR (Client-Side Rendering) и SSR (на стороне сервера Rendering).

  • вы можете реагировать на выборку действий, такие как загрузка данных или успех нагрузки в собственных редукторах

  • вы можете создать собственные межплатформенный для обработки Redux Асинхронного Connect действия
  • вы можете подключаться к загруженным данным в любом месте, просто используя простой перевождь @connect
  • наконец, вы можете отлаживать и увидеть ваши данные, используя Redux Dev Tools

  • Также он интегрирован с React Router для предотвращения маршрутизации transitio пока данные не будут загружены.

Убедитесь, что вы не забывайте 4 шага конфигурации (described here):

  1. Подключите данные, аналогичные реакции-перевождь @connect
  2. доступа к данным в качестве реквизита
  3. Подключить редуктор асинхронного редуктора
  4. Render Router с промежуточным программным обеспечением ReduxAsyncConnect

Таким образом, в DashboardPage (предполагающейgetWeatherReports()возвратит обещание), что мы можем сделать, это:

, если у вас есть Бабель пресеты для использования декораторов:

import { asyncConnect } from 'redux-connect'; 

@asyncConnect([{ 
    key: 'lunch', 
    promise: ({ store: { dispatch }, params }) => dispatch(getWeatherReports()) 
}]) 
export default class DashboardPage extends React.Component { 
... 
} 

в противном случае:

class DashboardPage extends React.Component { 
... 
} 


// sorry for the long name ;) 
const asyncConnectedDashboardPage = asyncConnect([{ 
    key: 'lunch', 
    promise: store.dispatch(getWeatherReports()) 
}]) 

export default asyncConnectedDashboardPage; 

Используйте обещание, кратной

@asyncConnect([{ 
    promise: ({ store: { dispatch, getState } }) => { 
    const promises = []; 
    const state = getState(); 
    if (/* some condition */) { 
     promises.push(dispatch(loadBlogs())) 
    } 

    if (/* some other condition */) { 
     promises.push(dispatch(loadUsers())) 
    } 

    promises.push(dispatch(getWeatherReports())) 
    return Promise.all(promises); 
    }, 
}]) 
+0

Есть ли способ сделать 'connect' метода этого использования React-Redux в? Я не могу быть единственным, кто имеет дело с этим, что заставляет меня думать, что я просто устанавливаю это неправильно. Тот факт, что я должен использовать другие зависимости, которые ... – Nappstir

Смежные вопросы