dan*_*gas 3 reactjs redux redux-thunk
我有点困惑,希望得到一个能帮助我理清思路的答案。假设我有一个后端(nodejs、express 等),我在其中存储我的用户及其数据,有时我想从后端获取数据,例如登录后的用户信息,或产品列表并保存他们在状态。
到目前为止,我的方法和我所看到的,我在组件加载之前获取数据并使用响应中的数据分派一个动作。但我最近开始深入研究这个,我看到了我之前知道的 react-thunk 库,并开始怀疑从后端/API 获取的最佳实践是什么?React Hooks 对这个话题有什么改变吗?知道这一点很重要吗?
我觉得有点傻,但找不到完全谈论这个话题的文章或视频:)
要执行此最佳实践,请使用以下方法:
我使用了一些包和模式以获得最佳实践:
通过创建名称的目录终极版或像你的任何名称src文件夹,然后创建两个文件
store.js,并rootReducer.js在终极版目录。我们假设从 API 获取产品。
去做这个:
通过创建名称的新目录的产品在终极版目录中,然后通过名称创建四个文件
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
...
Run Code Online (Sandbox Code Playgroud)
商店.js
在这个文件中我们进行了 redux 配置
// 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));
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
product.types.js 在这个文件中,我们定义了用于管理操作类型的常量。
export const ShopActionTypes = {
FETCH_PRODUCTS_START: "FETCH_PRODUCTS_START",
FETCH_PRODUCTS_SUCCESS: "FETCH_PRODUCTS_SUCCESS",
FETCH_PRODUCTS_FAILURE: "FETCH_PRODUCTS_FAILURE"
};
Run Code Online (Sandbox Code Playgroud)
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)));
};
};
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
product.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
);
Run Code Online (Sandbox Code Playgroud)
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")
);
Run Code Online (Sandbox Code Playgroud)
App.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);
Run Code Online (Sandbox Code Playgroud)
或带有功能组件( useEffect hook )的 App.js 在这个文件中,我们确实连接到带有功能组件的商店和状态
// 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);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1945 次 |
| 最近记录: |