Reducer更新了错误的值(数组已更新为一个项目内部有少量项目,而不是传播它们)

时间:2018-06-12 10:53:56

标签: javascript reactjs redux

我很难弄明白这一点。拥有搜索过滤器的组件并将所有选定的过滤器推送到url中。一切都像它应该的那样工作,除非在刷新的情况下,在这种情况下,reducer更新为选定的过滤器,带有单个项目的数组,其中我有所有选定的项目,而不是传播到数组。

f.e。我有网址

myexampleapp.com/alltrips?tripType=short_walk,cycling,downhill_cycling,long_walks&season=spring,summer,alle,vinter&lengthTo=50

我的减速机

// ------------------------------------
// Constants
// ------------------------------------
export const UPDATE_FILTERS = 'UPDATE_FILTERS';

// ------------------------------------
// Actions
// ------------------------------------
const updateFilter = (key, value) => ({
  type: UPDATE_FILTERS,
  payload: {
    key,
    value
  }
});

// ------------------------------------
// Action creators
// ------------------------------------
export const updateFilterState = (key, value) => {
  return dispatch => {
    dispatch(updateFilter(key, value));
  };
};

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  tripType: [],
  season: [],
  tripsTo: undefined,
  tripsFrom: undefined
};

export function filterReducer (state = initialState, action) {
  switch (action.type) {
  case UPDATE_FILTERS: {
    const key = action.payload.key;
    const value = action.payload.value;

    if (key === 'tripsFrom' || key === 'tripsTo') {
      return Object.assign({}, state, { [key]: value });
    } else {
      var newFilter = state[key].slice();
      var ttIdx = state[key].indexOf(value);

      if (ttIdx !== -1) {
        newFilter.splice(ttIdx, 1);
      } else {
        newFilter.push(value);
      }
    }
    console.log(newFilter);
    return Object.assign({}, state, { [key]: newFilter });
  }
  default:
    return state;
  }
}

console.log返回包含1个元素的数组,其中包含5个元素的数组。但是我想要5个ekements在parrent数组。 我正在解析网址

  componentDidMount () {
    let {
      location: { search },
      updateFilterState
    } = this.props;

    search = search.slice(1);
    var queries = search.split('&');
    queries.forEach(q => {
      var tmp = q.split('=');
      if (tmp[0] && tmp[1]) {
        if (tmp[0].toLowerCase() === 'triptype') {
          updateFilterState(tmp[0], tmp[1].split(','));
          console.log(tmp[1].split(','));
        } else if (tmp[0].toLowerCase() === 'tripsto') {
          updateFilterState(tmp[0], tmp[1]);
        } else if (tmp[0].toLowerCase() === 'tripsfrom') {
          updateFilterState(tmp[0], tmp[1]);
        } else if (tmp[0].toLowerCase() === 'season') {
          updateFilterState(tmp[0], tmp[1].split(','));
        }
      }
    });
    this.updateQuery(this.props);
  }

所以一切都有效,除非我想刷新。

这一切都很新,并且已经被困了将近3天。希望你明白我试图在这里问什么,因为我是一个非常新的非英语人士,所以我不知道所有的条款,所以我可以更好地表达自己。有人可以给我一些指示吗?

1 个答案:

答案 0 :(得分:1)

如果我没弄错的话,你会给减速器喂一个seasontripType的数组。因此,当您尝试更新这些值时,实际上并没有传播该数组。这是您的value参数。因此,如果您这样做,您将拥有一个包含所需结果的父数组:

newFilter.push(...value);

...ES6's spread syntax。所以我们正在传播我们的数组并将其推入我们的newFilter。

但是,如果我没有发现错误,您将会遇到此代码的问题,因为您没有检查您的值是否存在。你正在寻找indexOf的东西,但如果你真的给你的减速器喂一个数组,那么你正在看这个索引?

如果我没有弄错你在这里尝试做什么,这是一种更干净的方法:

export function filterReducer (state = initialState, action) {
  switch (action.type) {
  case UPDATE_FILTERS: {
    const { key, value } = action.payload;
    if (key === 'tripsFrom' || key === 'tripsTo') {
      return { ...state, [key]: value };
    }  
    const newFilter = Array.isArray(value)
                  ? [ ...new Set( [ ...state[key], ...value ] ) ]
                  : [ ...new Set( [ ...state[key], value ] ) ];
    return { ...state, [key]: newFilter};
  }
  default:
    return state;
  }
}

与您的代码存在一些差异:

  • 我使用的是spread语法而不是Object.assign。
  • 我没有检查所有存在值(迭代数组并做一些逻辑),而是使用Set object。它创造了一个我们赋予它的独特价值的对象。所以我在这里作弊并传播我们的旧状态,将我们的值传播到数组中,将它传递给我们的Set,再次在顶层将它再次传播到数组中。如果你不进行最后一次传播,你会得到一个对象,但在这里我们需要一个数组。