Функциональные компоненты React без сохранения состояния и жизненный цикл компонентов

Поэтому я просто переключился на использование функциональных компонентов без сохранения состояния в React с Redux, и мне было любопытно узнать о жизненном цикле компонентов. Изначально у меня было такое:

// actions.js

export function fetchUser() {
    return {
        type: 'FETCH_USER_FULFILLED',
        payload: {
            name: 'username',
            career: 'Programmer'
        }
    }
}

Затем в компоненте я использовал componentDidMount для получения данных следующим образом:

// component.js

...
componentDidMount() {
  this.props.fetchUser()
}
...

После перехода на функциональные компоненты без сохранения состояния у меня теперь есть контейнер с:

// statelessComponentContainer.js

...
const mapStateToProps = state => {
  return {
    user: fetchUser().payload
  }
}
...

Как видите, в настоящее время я не получаю данные асинхронно. Итак, мой вопрос: вызовет ли этот подход проблемы, когда я начну асинхронно получать данные? А также есть лучший подход?

Я просмотрел этот блог, где говорится: Если вашим компонентам нужны методы жизненного цикла, используйте классы ES6. Любая помощь будет оценена по достоинству.


person wmik    schedule 26.06.2017    source источник


Ответы (2)


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

Следование этому подходу, особенно после асинхронной выборки данных, означает, что вам придется учитывать состояние, в котором ваши данные еще не загружены. Для этого есть много вопросов и руководств (даже в другом ответе на этот вопрос), поэтому я не буду беспокоиться, чтобы привести здесь для вас пример.

Во-вторых, частым вариантом использования является асинхронная выборка данных при монтировании компонента. Желание написать красивый функциональный компонент - обычное желание. К счастью, у меня есть библиотека, которая позволяет вам делать и то, и другое: react-redux-lifecycle .

Теперь вы можете написать:

import { onComponentDidMount } from 'react-redux-lifecycle'
import { fetchUser } from './actions'

const User = ({ user }) => {
   return // ...
}

cont mapStateToProps = (state) => ({
  user = state.user
})

export default connect(mapStateToProps)(onComponentDidMount(fetchUser)(User))

Я сделал несколько предположений относительно имен ваших компонентов и структуры хранилища, но я надеюсь, что этого достаточно, чтобы донести идею. Я рада вам кое-что прояснить.

Отказ от ответственности: я являюсь автором библиотеки response-redux-lifecycle.

person Michael Peyper    schedule 26.06.2017

Не отображать представление, если еще нет данных. Вот как это сделать.

Подход к решению вашей проблемы - вернуть promise от this.props.fetchUser(). Вам необходимо dispatch выполнить свое действие с помощью response-thunk (см. Примеры и информацию о том, как настройка. Это просто!).

Ваше fetchUser действие должно выглядеть так:

export function fetchUser() {
  return (dispatch, getState) => {
      return new Promise(resolve => {
          resolve(dispatch({         
          type: 'FETCH_USER_FULFILLED',
          payload: {
            name: 'username',
            career: 'Programmer'
          }
        }))
      });
  };
}

Затем в вашем Component добавьте к методу жизненного цикла componentWillMount() следующий код:

componentDidMount() {
  this.props.fetchUser()
    .then(() => {
      this.setState({ isLoading: false });
    })
}

Конечно, ваш класс constructor должен иметь начальное состояние isLoading, установленное на true.

constructor(props) {
  super(props);

  // ...

  this.state({
    isLoading: true
  })
}

Наконец, в свой render() метод добавьте условие. Если ваш запрос еще не выполнен и у нас нет данных, напечатайте «данные все еще загружаются ...» в противном случае покажите <UserProfile /> Component.

render() {
  const { isLoading } = this.state;

  return (
    <div>{ !isLoading ? <UserProfile /> : 'data is still loading...' }</div>
  )
}
person loelsonk    schedule 26.06.2017
comment
Спасибо за это. Но означает ли это также, что я должен вернуться к классам es6? - person wmik; 26.06.2017
comment
Да, более сложная логика требует использования ES6 классов. - person loelsonk; 26.06.2017
comment
Понятно. Еще раз спасибо. - person wmik; 26.06.2017
comment
Если я помог вам, отметьте мой ответ как ответ. Также я обновил действие fetchUser. - person loelsonk; 26.06.2017