【问题标题】:How to transform the inner state based React app to Redux based?如何将基于内部状态的 React 应用程序转换为基于 Redux 的?
【发布时间】:2018-07-19 12:39:57
【问题描述】:

我编写了基于内部状态的 React 应用程序。它使用“axios”库从 Web API 获取数据。它看起来如下:

class OrdersTable extends React.Component {
  constructor() {
    super();

    this.state = {
      orders: [],
      ...
  }

  componentDidMount() {
    setTimeout(() => {
      axios.get("http://localhost:1234/api/orders").then(response => {
        this.setState({
          orders: response.data,
        });
      });
    }, 2000);
  }

  render () {
    return (
      <div className="content-wrapper">
        <div className="content-left">
           <BootstrapTable keyField='id' data={this.state.orders} columns={this.state.columns}
             rowStyle = {this.state.rowStyle} rowEvents={this.rowEvents}
             caption={<CaptionOrders title="Orders" />} noDataIndication={<NoData />} {...this.props} />
           <Legend />
        </div>
      </div>
    )
  }
}

我想将其转换为使用 Redux 而不是内部状态。我从以下开始:

index.js:

const store = createStore(reducer);

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

动作:

import { LOAD_DATA } from '../constants/action-types';

export const loadData = orders => ({
  type: LOAD_DATA,
  payload: orders
})

减速机:

export default initialState = {
  orders: []
};

const reducer = (state = initialState, action) => {
  switch(action.type) {
    case LOAD_DATA:
      return {
        ...state, orders: action.payload };
    default:
      return state;
  }
}

容器:

const mapStateToProps = (state) => ({
  orders: state.orders
})

const mapDispatchToProps = (dispatch) => ({
  // Should "axios" call be here and if so, how should look like?
});

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

演示组件:

How can I use the orders state from Redux in OrdersTable component?

【问题讨论】:

  • 您可以使用中间件将诸如 API 调用之类的异步操作转化为操作。一个常见的是redux-thunkredux.js.org/advanced/async-actions#async-action-creators
  • 谢谢,但我现在更喜欢使用经典方法。
  • 您不能在原版 Redux 中执行异步操作。你需要像redux-thunkredux-saga 这样的东西。

标签: javascript reactjs redux


【解决方案1】:

Redux 中的 HTTP 调用被视为副作用。它们不是 Redux 本身的一部分,它只是一个状态管理库。因此,除了 Redux 之外,您还必须使用另一个库,其中最简单的是 redux-thunk

使用 redux-thunk 你可以定义一个副作用,它本质上是一个可以分派多次的函数。例如:

import { LOAD_DATA } from '../constants/action-types';

export const getOrders = () => async (dispatch) => {
    try {
        const response = await axios.get("http://localhost:1234/api/orders");
        dispatch(loadData(response.data))
    } catch (e) {
        /* ... */
    }
}

export const loadData = orders => ({
type: LOAD_DATA,
payload: orders
})

【讨论】:

    【解决方案2】:

    Jayce444 是正确的,你应该使用 redux-thunk。我认为这是执行此操作的规范方法。

    看看这个答案:https://stackoverflow.com/a/34458710/8896573

    如果您想保持这种基本状态,请忘记 mapDispatchToProps(仍然使用 mapStateToProps),并在您的 axios 响应中调用 this.props.dispatch(loadData (orders))

    然后由于您的 mapStateToProps 的结构,您的“订单”在您的组件中可用 this.props.orders :)

    【讨论】:

    • 你的意思是从 OrdersTable 组件的 componentDidMount 内部的 "axios" 调用中调用 this.props.dispatch(loadData(orders)) 吗?
    • 你我会试试的。我没试过。但我会试试看。但最终你应该尝试 redux-thunk。你试过了吗?
    猜你喜欢
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    相关资源
    最近更新 更多