【问题标题】:Action creators handling axios get.request with state access for param处理 axios get.request 的动作创建者对参数的状态访问
【发布时间】:2016-09-08 22:12:46
【问题描述】:

我正在尝试将一些值从组件传递给正在使用 axios 执行获取请求的操作创建者。我正在尝试遵循 Dan Abramov 的这种模式:

export const SOME_ACTION = 'SOME_ACTION';
export function someAction() {
  return (dispatch, getState) => {
    const {items} = getState().otherReducer;

    dispatch(anotherAction(items));
  }
}

但是我不能让它工作。我认为我在两个层面上遇到了麻烦:我的组件和我的动作创建者。能得到一些帮助会很棒。

我的组件:

const timeR = ({ 
  selectedTimeRange,
  timeRange = [],
  onTimeChange }) => {
  return (
    <div>
      <div>
        Filters:
        <div>
          Year:
          <select
            defaultValue={selectedTimeRange}
            onChange={onTimeChange}>
            <option value="all" >All</option>
            {timeRange.map((y, i) =>
              <option key={i} value={y}>{y}</option>
            )}
          </select>
        </div>
    </div>
  </div>
  );
}


function mapStateToProps(state) {
    var range = ['30daysAgo', '15daysAgo', '7daysAgo'];
  return {
      selectedTimeRange: state.timeReducer.timerange[0],
      timeRange: range 
  };
};

const mapDispachToProps = (dispatch) => {
  return {
  onTimeChange: (e) => {dispatch (onSetTimeRange(e.target.value));},

  };
};

const TimeRange = connect(mapStateToProps, mapDispachToProps)(timeR);

export default TimeRange;

这个组件给了我一个下拉菜单。选择时间范围时,例如“30daysAgo”,它会更新我的 redux 存储状态,以便我可以从 reducer 访问值。

这是与我的下拉菜单关联的操作:

export function onSetTimeRange(timerange) {
 return {
        type: 'SET_TIME_RANGE',
        timerange
    }
}

这是处理 axios.get 的操作:

export const fetchgadata = () => (dispatch) => {
    dispatch({
        type: 'FETCH_DATA_REQUEST',
        isFetching:true,
        error:null
  });

var VIEW_ID = "ga:80820965";

return axios.get("http://localhost:3000/gadata", {
  params: {
    id: VIEW_ID
  }
}).then(response => {
      dispatch({
            type: 'FETCH_DATA_SUCCESS',
            isFetching: false,
            data: response.data.rows.map( ([x, y]) => ({ x, y }) )
      });
    })
    .catch(err => {
      dispatch({
            type: 'FETCH_DATA_FAILURE',
            isFetching:false,
            error:err
      });
      console.error("Failure: ", err);
    });
};

我的问题:

如何将这两个操作结合在一起。最后,我希望能够在我的下拉菜单上执行onChange 时,使用从我的菜单中选择的值作为我的 axios.get 请求的参数来调用一个操作。

我觉得我需要嵌套两个动作创建者。我已经尝试过了,但不起作用(我的终端出现"fetchgadata" is read-only 错误)

export const SET_TIME_RANGE = 'SET_TIME_RANGE';
export function onSetTimeRange() {
  return (dispatch, getState) => {
    const {VIEW_ID} = getState().timerange;

    dispatch(fetchgadata = (VIEW_ID) => (dispatch) => {
    dispatch({
        type: 'FETCH_DATA_REQUEST',
        isFetching:true,
        error:null,
        id:VIEW_ID,
  });
  });

return axios.get("http://localhost:3000/gadata", {
  params: {
    id: VIEW_ID
  }
}).then(response => {
      dispatch({
            type: 'FETCH_DATA_SUCCESS',
            isFetching: false,
            data: response.data.rows.map( ([x, y]) => ({ x, y }) )
      });
    })
    .catch(err => {
      dispatch({
            ype: 'FETCH_DATA_FAILURE',
            isFetching:false,
            error:err
      });
      console.error("Failure: ", err);
    });
}
  }

编辑:

API 调用的减速器:

const initialState = {data:null,isFetching: false,error:null};
export const gaData = (state = initialState, action)=>{
    switch (action.type) {
        case 'FETCH_DATA_REQUEST':
        case 'FETCH_DATA_FAILURE':
        return { ...state, isFetching: action.isFetching, error: action.error };

        case 'FETCH_DATA_SUCCESS':
        return Object.assign({}, state, {data: action.data, isFetching: action.isFetching,
                 error: null });
        default:return state;

    }
};

下拉减速器:

const items = [{timerange: '30daysAgo'},{timerange: '15daysAgo'},{timerange: '7daysAgo'}] 

const timeReducer = (state = { 
  timerange: items 
  }, action) => { 
    switch (action.type) {
      case 'SET_TIME_RANGE':
      console.log(state,action);
              return {
        ...state,
        timerange: action.timerange,
      };
    default:
      return state;

        }
    }

【问题讨论】:

    标签: asynchronous reactjs react-redux redux-thunk


    【解决方案1】:

    我在您的 axios.get 请求的捕获中看到了一个小错字,它显示为 ype: FETCH_DATA_FAILURE。否则,你能帮我添加你的减速器吗,我在上面看不到?如果我理解正确,您希望一个操作更新两个不同的状态,在这种情况下,您只需调度一个操作并将其添加到两个减速器。最好只是演示一下:

    //axios call
    axios.get("some route", { some params } )
    .then(response => { 
        dispatch({
          type: UPDATE_TWO_THINGS,
          payload: some_value
        })
    }) .... catch, etc
    
    //reducer 1
    import { UPDATE_TWO_THINGS } from 'types';
    
    const INITIAL_STATE = { userInfo: '' };
    
    export default function (state = INITIAL_STATE, action) {
      switch(action.type) {
       case UPDATE_TWO_THINGS:
         return {...state, userInfo: payload };
      }
    
      return state;
    }
    
    //reducer 2
    import { UPDATE_TWO_THINGS } from 'types';
    
    const INITIAL_STATE = { businessInfo: '' };
    
    export default function (state = INITIAL_STATE, action) {
      switch(action.type) {
       case UPDATE_TWO_THINGS:
         return {...state, businessInfo: payload };
      }
    
      return state;
    }
    

    希望这会有所帮助,但如果没有,请告诉我,我会尽力与您合作!谢谢提问!

    【讨论】:

    • 嗯...我不确定这是否真的是我想要的。我的意思是我想要一个动作来更新两个不同的状态。但是我想用第一个状态来更新第二个状态。在我的示例中,我需要使用时间范围来更新我的谷歌分析 api 调用。换句话说selecting a time range -> '将这个时间范围传递给我的 axios.get... but yes I want this two step happen after on onChange` 事件。是不是更清楚了?
    • 嗨西蒙,很抱歉这么久才回复。你所要求的有点令人不悦,通常意味着你需要重新考虑你的动作/减速器关系。这是我发现的一篇很棒的文章,它简要解释了为什么它不是一个好主意,然后继续解释如果你坚持要如何做到这一点。 jamesknelson.com/…
    • 是的。你是对的。我终于解决了我的问题。但是我仍然不知道我是怎么做到的。只需调整我的代码。在写出正确的答案之前,需要把这一切弄清楚。
    猜你喜欢
    • 2016-06-10
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 2016-04-29
    • 2021-02-01
    • 2018-07-23
    • 1970-01-01
    相关资源
    最近更新 更多