将数据POST到服务器并使用redux处理响应的正确方法

Evo*_*tio 0 reactjs redux react-redux

我很反应和减少.

现在我想用redux进程重写我的post请求.

我当前的请求如下所示:

  _handleSubmit(event) {
    axios
      .post('/createUrl', {
        url: this.state.url
      })
      .then((response) => {
        this.setState({
          shortenInfos: response.data
        })
      })
      .catch((error) => {
        console.log(error);
      });

    event.preventDefault()
  }
Run Code Online (Sandbox Code Playgroud)

现在我创建了一个商店:

export default function url(state = 0, action) {
  switch (action.type) {
    case 'CREATE_URL':
      // maybe axios request?!
      return `${action.url}/test`
    case 'CREATED_URL':
      return `${action.url}/created`
    default:
      return state
  }
}
Run Code Online (Sandbox Code Playgroud)

所以我必须使用store.dispatch()?我应该让我的_handle提交这样的东西吗?

_handleSubmit(event) {
  axios
    .post('/createUrl', {
      url: this.state.url
    })
    .then((response) => {
      store.dispatch({
        type: 'CREATED_URL',
        url: response.data
      })
    })
    .catch((error) => {
      console.log(error);
    });

  event.preventDefault()
}
Run Code Online (Sandbox Code Playgroud)

我觉得这是错的?我必须在哪里使用mapStateToProps方法?或者我应该在我的reducer中的CREATE_URL中执行axios-request?

tot*_*dli 7

介绍

将React与Redux结合使用,可以让您高度自由地执行操作.这样做的缺点是很难找到应该如何正确完成的事情,主要是因为没有标准或全面的指南来使用正确实现项目所需的许多依赖项.这个答案将指导您完成基础知识,并提供参考链接,帮助您了解下一步以及如何深入了解您的知识.

减速器

Reducers应该是纯粹的,这意味着它们没有副作用(比如发出axios请求),它们应该总是返回一个新的对象/数组/值,而不是改变以前的状态.将动作类型用作常量也是一种很好的做法.您可以在任何地方放置动作类型,但为了简单起见,我会将它们放入reducer的文件中,但有更好的方法来组织它们,就像使用ducks一样.

export const CREATED_URL = 'CREATE_URL';

export default const url = (state = '', action) => {
  switch (action.type) {
    case CREATED_URL:
      return action.url;
    default:
      return state;
  }
};
Run Code Online (Sandbox Code Playgroud)

异步动作

导致副作用的一切都应该是一个动作,所以XHR应该在那里发生.因为XHR应该是异步的,所以建议使用中间件:redux-thunkredux-saga是两种流行的解决方案.我会选择thunk,然后先安装它.

首先(因为const有临时死区)你需要一个动作,将XHR的结果"加载"到商店:

import { CREATED_URL } from './reducer';

const createdUrl = url => ({
  type: CREATED_URL,
  url, // ES6 trailing comma for prettier git diffs
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建将触发XHR的操作,等待响应,然后使用先前创建的操作将其加载到商店.我们需要返回一个将dispatch作为参数接收的函数.这种技术用于函数式编程,称为currying.

export const createUrl = url => dispatch => { // with only 1 parameter the parentheses can be omited
  axios
    .post('/createUrl', { url }) // ES6 Shorthand property name in { url }
    .then(response => {
      dispatch(createdUrl({
        url: response.data,
      })
    })
    .catch(error => {
      // @TODO dispatch an action that will show a message
      // notifying the user that the request failed
      console.log(error);
    }); 
}
Run Code Online (Sandbox Code Playgroud)

在React组件中的用法.

制备

为了便于使用,您需要将React组件与Redux连接.react-redux来救援.阅读API文档并将<Provider>组件添加到React组件树的根目录中.

现在,在React组件文件的顶部,导入所有必要的东西:

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { createUrl } from './reducer';
Run Code Online (Sandbox Code Playgroud)

mapStateToPropsmapDispatchToProps

然后创建两个辅助函数connect:

const mapStateToProps = store => ({ url: store.url })

const mapDispatchToProps = dispatch => bindActionCreators({ createUrl }, dispatch)
Run Code Online (Sandbox Code Playgroud)

mapStateToProps您的帮助下,您可以订阅商店更新并将Redux商店的重要部分注入您的组件props.mapStateToProps应该返回一个将合并到组件的对象props.通常我们只是做类似的事情,store => store.url但是因为我们的示例非常简单以至于reducer返回一个普通字符串而不是对象中更复杂的东西,我们需要将该字符串包装到此处的对象中.

mapDispatchToProps借助于bindActionCreators将传递的动作注入组件props,我们可以轻松调用并将它们传递给子组件:this.props.createUrl().

组件本身

现在我们可以创建组件本身.我将使用ES6类来展示一个示例componentDidMount,但是如果您不需要它并且您有一个无状态组件,那么您也可以使用一个函数.

class Example extends React.Component {

  componentDidMount() {
    // If you need to load data from a remote endpoint place the action call here, like so:
    // this.props.createUrl('your-url');
  }

  render() {
    return (
      <div>
        <div>URL injected from the store, automatically refreshed on change: {this.props.url}</div>
        <div onClick={event => {this.props.createUrl('your-url');}}>Click me to fetch URL</div> 
      </div>
    )
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Example)
Run Code Online (Sandbox Code Playgroud)