Реагировать на выборку данных Redux из бэкэнд-подхода - PullRequest
1 голос
/ 19 февраля 2020

Я немного растерялся и хотел бы получить ответ, который поможет мне прояснить мысли. Допустим, у меня есть бэкэнд (nodejs, express et c ..), где я храню своих пользователей и их данные, и иногда я хочу получить данные из бэкэнда, такие как информация о пользователе после того, как он вошел в систему, или список продуктов и сохранить их в состоянии.

Мой подход и то, что я видел, я выбираю данные до загрузки компонента и отправляю действие с данными из ответа. Но недавно я начал немного копаться в этом вопросе и увидел библиотеку реагирования, которую я знал ранее, и начал задаваться вопросом, каков наилучший способ получения из бэкэнда / API? Изменили ли React Hooks что-нибудь об этом topi c? Важно ли это знать?

Я чувствую себя немного глупым, но не могу найти статью или видео, в которых точно говорится об этом топи c:)

1 Ответ

4 голосов
/ 20 февраля 2020

Для этого рекомендуется использовать следующий метод:

Для лучшего опыта я использовал несколько пакетов и шаблонов:

  • redux-logger для журнала действия и состояния в консоли браузера.
  • повторный выбор Селекторы могут вычислять производные данные, позволяя Redux сохранять минимально возможное состояние и т. д. c.
  • redux-thunk Thunks - это рекомендуемое промежуточное программное обеспечение для основных побочных эффектов Redux logi c, включая сложные синхронные логики c, которым требуется доступ к хранилищу, и простые asyn c logi c, такие как AJAX запросы и др. c.
  • ax ios для работы с API (HTTP-клиент на основе Promise для браузера и node.js)

создайте каталог с именем redux или любым другим именем в sr c folder , а затем создайте два файла store.js и rootReducer.js в каталоге redux. Мы предполагаем получать продукты из API.

Для этого:

Создайте новый каталог с именем product in redux затем создайте четыре файла с именами product.types.js, product.actions.js, product.reducer.js, product.selector.js в redux/product каталог

Структура проекта должна быть следующей:

...
src
  App.js
  redux
    product
      product.types.js
      product.actions.js
      product.reducer.js
    rootReducer.js
    store.js
 Index.js
package.json
...

store. js

В этом файле мы выполняем настройку редукса

// redux/store.js:
import { createStore, applyMiddleware } from "redux";
import logger from "redux-logger";
import thunk from "redux-thunk";

import rootReducer from "./root-reducer";

const middlewares = [logger, thunk];

export const store = createStore(rootReducer, applyMiddleware(...middlewares));

rootReducer. js

Вспомогательная функция combineReducers превращает объект, значения которого являются различными сокращающими функциями, в одну сокращающую функцию, которую вы можете передать createStore.

// redux/rootReducer.js
import { combineReducers } from "redux";

import productReducer from "./product/product.reducer";

const rootReducer = combineReducers({
  shop: productReducer,
});

export default rootReducer;

product.types. js В этом файле мы определяем константы для управления типами действий.

export const ShopActionTypes = {
  FETCH_PRODUCTS_START: "FETCH_PRODUCTS_START",
  FETCH_PRODUCTS_SUCCESS: "FETCH_PRODUCTS_SUCCESS",
  FETCH_PRODUCTS_FAILURE: "FETCH_PRODUCTS_FAILURE"
};

product.actions. js В этом файле мы создаем создателей действий для действий дескриптора .

// redux/product/product.actions.js
import { ShopActionTypes } from "./product.types";
import axios from "axios";

export const fetchProductsStart = () => ({
  type: ShopActionTypes.FETCH_PRODUCTS_START
});

export const fetchProductsSuccess = products => ({
  type: ShopActionTypes.FETCH_PRODUCTS_SUCCESS,
  payload: products
});

export const fetchProductsFailure = error => ({
  type: ShopActionTypes.FETCH_PRODUCTS_FAILURE,
  payload: error
});

export const fetchProductsStartAsync = () => {
  return dispatch => {
    dispatch(fetchProductsStart());
    axios
      .get(url)
      .then(response => dispatch(fetchProductsSuccess(response.data.data)))
      .catch(error => dispatch(fetchProductsFailure(error)));
  };
};

product.reducer. js В этом файле мы создаем productReducer функцию для действий с ручками.

import { ShopActionTypes } from "./product.types";

const INITIAL_STATE = {
  products: [],
  isFetching: false,
  errorMessage: undefined,
};

const productReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case ShopActionTypes.FETCH_PRODUCTS_START:
      return {
        ...state,
        isFetching: true
      };
    case ShopActionTypes.FETCH_PRODUCTS_SUCCESS:
      return {
        ...state,
        products: action.payload,
        isFetching: false
      };
    case ShopActionTypes.FETCH_PRODUCTS_FAILURE:
      return {
        ...state,
        isFetching: false,
        errorMessage: action.payload
      };
    default:
      return state;
  }
};

export default productReducer;

prod uct.selector. js В этом файле мы выбираем products и isFetching из состояния магазина.

import { createSelector } from "reselect";

const selectShop = state => state.shop;

export const selectProducts = createSelector(
  [selectShop],
  shop => shop.products
);

export const selectIsProductsFetching = createSelector(
  [selectShop],
  shop => shop.isFetching
);

Index. js В этот файл упакован все приложение и компоненты с Provider для доступа дочерних компонентов к хранилищу и состояниям.

// src/Index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

import { Provider } from "react-redux";
import { store } from "./redux/store";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

приложение. js компонент класса В этом файле мы подключаемся к хранилищу и Состояния с компонентом класса

// src/App.js
import React, { Component } from "react";

import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
  selectIsProductsFetching,
  selectProducts
} from "./redux/product/product.selectors";

import { fetchProductsStartAsync } from "./redux/product/product.actions";

class App extends Component {
  componentDidMount() {
    const { fetchProductsStartAsync } = this.props;
    fetchProductsStartAsync();
  }

  render() {
    const { products, isProductsFetching } = this.props;
    console.log('products', products);
    console.log('isProductsFetching', isProductsFetching);
    return (
      <div className="App">Please see console in browser</div>
    );
  }
}

const mapStateToProps = createStructuredSelector({
  products: selectProducts,
  isProductsFetching: selectIsProductsFetching,
});

const mapDispatchToProps = dispatch => ({
  fetchProductsStartAsync: () => dispatch(fetchProductsStartAsync())
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

или Приложением. js с функциональным компонентом (хук useEffect) В этом файле мы подключаемся к хранилищу, а состояния с функциональным компонентом

// src/App.js
import React, { Component, useEffect } from "react";

import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
  selectIsProductsFetching,
  selectProducts
} from "./redux/product/product.selectors";

import { fetchProductsStartAsync } from "./redux/product/product.actions";

const App = ({ fetchProductsStartAsync, products, isProductsFetching}) => {
  useEffect(() => {
    fetchProductsStartAsync();
  },[]);

    console.log('products', products);
    console.log('isProductsFetching', isProductsFetching);

    return (
      <div className="App">Please see console in browser</div>
    );
}

const mapStateToProps = createStructuredSelector({
  products: selectProducts,
  isProductsFetching: selectIsProductsFetching,
});

const mapDispatchToProps = dispatch => ({
  fetchProductsStartAsync: () => dispatch(fetchProductsStartAsync())
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);
...