2017-02-09 18 views
0

Я наткнулся на требование на участке вагона JS Webapp, для которого требуется отдельный объект определения «JSON» для рендеринга. Определения загружены через HTTP запрос в самом начале, прочитать, разобрать и передать на другой уровень приложения. Сам объект никогда не изменяется на протяжении всего жизненного цикла.Обработать асинхронные действия, которые не сохраняют результат в состоянии

Я сейчас пытаюсь смоделировать этот сценарий в ReactJS, используя Redux + redux-thunk. Я создал действие thunk/async, извлекает объект JSON, извлекает все, что ему нужно, и заканчивает обновление состояния с этим - , но он не хранит сам объект. Это кажется правильным, логичным подходом, поскольку, как уже упоминалось, определения никоим образом не изменяются. Я бы сказал, что это просто не указано, в строгом смысле слова.

Однако, приняв это решение, я в конечном итоге боролся при реализации фактического React.Component. Почти каждый example я видел там в дикой природе для асинхронных случаев, подобных этому:

  • Определяет действие стука, что пожары некоторого API вызова.
  • Хранит все, что бы они ни вернули (или после некоторых изменений) в государственной собственности.
  • Сохранилось, что это свойство было this.props в компоненте с mapStateToProps и connect.

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

class ContainerComponent extends React.Component { 
    state = { definitions: {} }; 

    componentDidMount() { 
    const { dispatch } = this.props; 
    dispatch(fetchDefinitions()) 
     .then((definitions) => this.setState({ definitions })); 
    } 

    render() { 
    return (<PresentationalComponent definitions={this.state.definitions} />); 
    } 
} 

export default connect()(ContainerComponent); 

Не говоря, что this.setStatebe avoided должен, но это выглядит очень много, как то, что я еще до введения Redux: API вызов возвращается обещание - только с гораздо больше с вмешательством indirections.

componentDidMount() { 
    const { dispatch } = this.props; 
    fetch(`${API_URL}/definitions`) 
     .then((res) => res.json()) 
     .then((definitions) => this.setState({ definitions })); 
    } 

Итак, как мне это сделать? Есть ли какая-то особенная вещь, которую я здесь отсутствует? Любой образец, которым я должен следовать? Возможно, избегая Redux полностью для этого?

ответ

2

Вы правы в том, что наличие состояния компонента не обязательно является плохим, но я считаю, что вы смущены тем, где хранить эти данные после вызова API.

Вы упомянули, что это не обязательно состояние, но я бы сказал иначе. Перед вызовом API ваше приложение не имеет этих данных. У вас могут быть определенные индикаторы UX/UI при запуске приложения, которые, например, могут указывать, будут ли данные извлекаться: definitions.all.isFetching.

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

import { assign, get } from 'lodash'; 

const all = (
    state = { isFetching: false, data: [] }, 
    action, 
) => { 
    switch (action.type) { 
    case types.LIST_DEFINITIONS: 
     return assign({}, state, { isFetching: true }); 
    case types.LIST_DEFINITIONS_SUCCESS: 
     return assign({}, state, get(action, 'result.data'), { isFetching: false }); 
    default: return state; 
    } 
}; 

Тогда в компоненте, вы бы connect вашего перевождь магазин

function mapStateToProps(state){ 
    return { 
    definitions: state.definitions.all.data 
    }; 
} 
export default connect(mapStateToProps, { listDefinitions })(ContainerComponent); 

Также Заметьте, что я перенесла действие в моем примере и помещаю его в соединение с сокращением mapDispatchToProps.

+0

ОК. Ваше объяснение имеет смысл для меня - в некоторой степени. Ваш аргумент для включения огромного (не упоминал об этом, но он довольно большой в моем случае), почти бесполезный объект после его первого (и единственного) использования в общем состоянии показывает какой-то счетчик? Не похоже на хороший компромисс. Кроме того, я мог бы справиться с этим и с местным государством. Разве это не похоже на то, чтобы попытаться вместить решение в рамки? –

+1

Redux - это просто инструмент управления государством. Вы можете использовать, если хотите, но вам это не нужно. Все, что вы делаете в разработке своего приложения, зависит от вас, и есть много способов для подобных целей. Всякий раз, когда я создаю приложение, я учитываю, когда запрос на API выходит из строя. Я не могу гарантировать, что мои «определения» всегда будут возвращаться ко мне, и я хотел бы, чтобы UX/UI был разработан, чтобы отражать, когда ответ получен или получен моим приложением. Если у вас есть функциональность и организационная структура, которые вам нужны без redux, не стесняйтесь ее удалять - это ваше приложение в конце концов. –

+1

Достаточно честный. Мой вопрос был больше в строках: «Есть ли другой подход к этому, чем то, что я сделал?». Вы, конечно, дали один. Я принимаю ваш ответ. Благодаря! –