将函数从纯React转换为Redux React

时间:2019-10-04 10:18:15

标签: javascript reactjs redux react-redux

在纯粹的反应中,我编写了一个在componentDidMount ()中调用的函数:

  getTasks = (userId, query, statusTask, pageNumber) => {
    let check = {};
    axios({
      url: `/api/v1/beta/${userId}`,
      method: 'GET'
    })
      .then(res => {
        check = res.data;

        if (res.data) {
          this.setState({
            checkRunning: res.data,
            checkRunningId: res.data.id
          });
          this.utilizeTimes(res.data.task_id);
        }
      })
      .catch(error => {
        console.log(error);
      })
      .then(() => {
        const params = {
          sort: 'name'
        };

        if (query) {
          params['filter[qwp]'] = query;
          if (this.state.tasks[0]) {
            this.setState({
              selectedId: this.state.tasks[0].id,
              selectedTabId: this.state.tasks[0].id
            });
          }
        }

        axios({
          url: '/api/v1//tasks',
          method: 'GET',
          params
        })
          .then(res => {
            if (res.status === 200 && res.data) {
              this.setState({
                tasks: res.data,
                lengthArrayTasks: parseInt(res.headers['x-pagination-total-count'])
              });

              if (!check && res.data && res.data[0]) {
                this.setState({
                  selectedTabId: res.data[0].id,
                });

                this.load(res.data[0].id);
              }

              let myArrayTasks = [];
              myArrayTasks = res.data;
              let findObject = myArrayTasks.find(task => task.id === this.state.runningTimerTask.id);

              if (
                !findObject &&
                this.state.runningTimerTask &&
                this.state.runningTimerTask.id &&
                this.state.query === ''
              ) {
                this.setState({
                  tasks: [this.state.runningTimerTask, ...myArrayTasks]
                });
              }
            }
          })
          .catch(error => {
            console.log(error);
          });
      });
  };

我正在尝试将其重写为redux,但效果不佳。首先,它发出一个请求/ api / v1 / beta / $ {userId},将答案写到变量check中。 check传递到下一个then。在下一个then中执行请求'/ api / v1 //任务'有人可以帮我吗?我要求一些提示。这有点复杂吗?

到目前为止,我已经设法创建了这样的东西:

商店

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';

const store = createStore(rootReducer, applyMiddleware(thunk));

export default store;

动作

export const RUNNING_TIMER = 'RUNNING_TIMER';
export const GET_TASKS = 'GET_TASKS';
export const FETCH_FAILURE = 'FETCH_FAILURE';

export const runningTimer = (userId, query, statusTask, pageNumber) => dispatch => {
  console.log(userId);
  axios({
    url: `/api/v1/beta/${userId}`,
    method: 'GET'
  })
    .then(({ data }) => {
      dispatch({
        type: RUNNING_TIMER,
        payload: data
      });
    })
    .catch(error => {
      console.log(error);

      dispatch({ type: FETCH_FAILURE });
    })
    .then(() => {
      const params = {
        sort: 'name'
      };

      axios({
        url: '/api/v1//tasks',
        method: 'GET',
        params
      })
        .then(({ data }) => {
            dispatch({
                type: GET_TASKS,
                payload: data
            });
        })
        .catch(error => {
            console.log(error);
        });
    });
};

减速器

import { RUNNING_TIMER, GET_TASKS } from '../actions';

const isRunningTimer = (state = {}, action) => {
  const { type, payload } = action;
  switch (type) {
    case RUNNING_TIMER:
      return {
        checkRunningTimer: payload,
        checkRunningTimerId: payload && payload.id ? payload.id : null
      };
      break;
      case GET_TASKS:
      return {
        tasks: payload,
        lengthArrayTasks: parseInt(action.headers['x-pagination-total-count'])
      };
    default:
      return state;
  }
};

const rootReducer = combineReducers({ isRunningTimer });

export default rootReducer;

应用

class App extends Component {
  constructor() {
    super();
    this.state = {
      name: 'React'
    };
  }

  componentDidMount() {
    this.props.runningTimer();
  }

  render() {
    return (
      <div>

      </div>
    );
  }
}

const mapStateToProps = state => {
  const { isRunningTimer } = state;

  return {
    isRunningTimer
  };
};

const mapDispatchToProps = dispatch => ({
  runningTimer: (userId, query, statusTask, pageNumber) => dispatch(runningTimer()),
});

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

3 个答案:

答案 0 :(得分:6)

数字1考虑您的状态设计。

我发现考虑状态对象在给定时间点的外观会很有用。

这是我的应用程序中使用的initialState的示例。

const initialState = {
        grocers: null,
        coords: {
            latitude: 37.785,
            longitude: -122.406
        }

    };

这被注入到createStore中。

分解应用程序状态对象/属性,应该也可以帮助您简化操作。

数字2

考虑分解您的动作。

我的想法是,将动作代码与分开,然后在.then 分开(考虑将结果保存在用户:object中)

        .then(response => {
          const data = response.data.user;
          setUsers(data);})
        .catch(error => {
            console.log('There has been a problem with your fetch operation: ' + error.message);
        })

    function setUsers(data){
        dispatch({
            type: FETCH_USERS,
            payload: data
        });
    }

这是指SOLID设计原则中的S。单一责任原则。

https://devopedia.org/solid-design-principles

数字3

如果“ getUser”信息获取失败,请考虑一下。

将流程/响应分开,将使应用程序的调试更加干净。例如,用户api失败或getTask api失败,等等。


有关redux的更多资源。 https://redux.js.org/introduction/learning-resources#thinking-in-redux

答案 1 :(得分:3)

扩展了@Cullen的先前答案,这是我所做的:

  1. 由于您已经有对GET_TODOS的操作,因此只需让runningTimer的操作创建者做一件事情就可以-向/api/v1/beta/<userId>进行API调用并分派相应的操作。
export const runningTimer = (
  userId,
  query,
  statusTask,
  pageNumber
) => dispatch => {
  return axios({
    url: `/api/v1/beta/${userId}`,
    method: "GET"
  })
    .then(({ data }) => {
      dispatch({
        type: RUNNING_TIMER,
        payload: data
      });
    })
    .catch(error => {
      console.log(error);

      dispatch({ type: FETCH_FAILURE });
    });
};

  1. 更新应用程序组件的道具以读取商店数据。
...
const mapStateToProps = state => {
  const { isRunningTimer, todos, todo } = state;

  return {
    todos,
    todo,
    isRunningTimer,
  };
};

const mapDispatchToProps = dispatch => ({
  getTodos: () => dispatch(getTodos()),
  getTodo: id => dispatch(getTodo(id)),
  runningTimer: (userId, query, statusTask, pageNumber) => dispatch(runningTimer(userId)),
});
...
  1. 更新componentDidMount的实现以调度isRunningTimer-
componentDidMount() {
...
    // call with userId 1
    this.props.runningTimer(1).then(() => {
      console.log(this.props);

          // additional params for getTasks
      const params = {
        sort: 'name'
      };

      // another call for getTodos with names sorted
      this.props.getTodos(params);
    });
...

  

注意:您需要更新getTodos动作以采用可选的params参数(如果未传递,则初始化为空对象)。

希望这对您有所帮助。

此处有实时沙箱-https://stackblitz.com/edit/react-redux-more-actions

答案 2 :(得分:0)

签出React-boilerplate。伟大的样板反应和还原。他们也使用redux-sagaredux-hooks