Converting functions from pure react to redux react

落花浮王杯 提交于 2021-02-07 18:21:29

问题


In pure react, I have written a function that I call in 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);
          });
      });
  };

I am trying to rewrite it to redux, but with poor results. First it makes one request / api / v1 / beta / $ {userId}, writes the answer in the variable check. check passes to the nextthen. In the next then carries out the request '/ api / v1 // tasks' Can somebody help me? I am asking for some tips. Is this somehow complicated?

So far, I've managed to create something like this:

store

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

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

export default store;

actions

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);
        });
    });
};

reducer

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;

App

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);

回答1:


Number 1 Consider your state design.

I find it useful to consider what the state object would look like at a given point in time.

Here is an example of initialState used in an application of mine.

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

    };

This is injected at the createStore.

Breaking down your application state object/properties, should assist you in making your actions simpler as well.

Number 2

Consider breaking down your actions.

My thoughts, decouple the action code, at the .then at the second .then .(Consider saving the results somewhere in a user: 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
        });
    }

This refers to the S in SOLID design principles. Single Responsibility Principle.

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

Number 3

Consider this, if the 'getUser' info fetch fails.

Having the process/response separated will allow the application to be debugged more cleanly. In example, the user api failed or the getTask api failed, etc.


More resources on redux. https://redux.js.org/introduction/learning-resources#thinking-in-redux




回答2:


Extending previous answer from @Cullen, this is what I did:

  1. Since you already have a action to GET_TODOS, just make the action creator for runningTimer to do one and only one thing - make API call to /api/v1/beta/<userId> and dispatch respective actions.
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. Update props of your app component to read store data.
...
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. Update the implementation of componentDidMount to dispatch 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);
    });
...

Note: You need to update your getTodos action to take in an optional params arguments (which is initialized to empty object if not passed).

Hope this helps you.

Live sandbox for this is present here - https://stackblitz.com/edit/react-redux-more-actions




回答3:


Check out React-boilerplate. Great boilerplate for react and redux. They use redux-saga and redux-hooks as well.



来源:https://stackoverflow.com/questions/58234442/converting-functions-from-pure-react-to-redux-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!