javascript - 如何使用 Redux 过滤数据但保持旧状态?

标签 javascript reactjs ecmascript-6 redux react-redux

我正在使用 Redux 开发搜索功能,但遇到了一些问题。

这些是与搜索内容相关的操作:

export const passengersDataAction = passengersData => ({
  type: ActionTypes.PASSENGERS_DATA,
  // This is the array of objects that I need to search through
  payload: { passengersData }, 
});

export const searchParamAction = searchParam => ({
  type: ActionTypes.SEARCH_PARAM,
  // This is the param that I need to send to passengersData
  // in order to get a new array of objects based on the searchParam
  payload: { searchParam },
});

reducer :

const initialState = {
  passengersData: [],
  searchParam: '',
};

const handlers = {
  [ActionTypes.PASSENGERS_DATA](state, action) {
    return {
      ...state,
      passengersData: action.payload.passengersData,
    };
  },

  [ActionTypes.SEARCH_PARAM](state, action) {
    return {
      ...state,
      searchParam: action.payload.searchParam,
    };
  },
};

顺便说一句,这是对象数组的样子:

[
 {
  "id": 3,
  "name": "Marcos Alonso",
  "address": "Sabana",
  "phone": "712321222",
  "pickup": 0,
  "cardinalpoint": "N",
  "latitude": "9.93683450",
  "longitude": "-84.10991830",
  "timestamp": "2019-02-19 21:23:46",
  "dropofftimestamp": null,
  "pickuptimestamp": null,
  "deleted": null,
  "driver": 1
 },
 ...
]

这是我正在努力让它发挥作用的东西:

   [ActionTypes.SEARCH_PARAM](state, action) {
    //In filter you can add your own logic to get the data
    const searchedData = state.passengersData.filter((passenger) => passenger.name === action.payload.searchParam);

       return {
         ...state,
         passengersData: searchedData,
         searchParam: action.payload.searchParam,
       };
    },

但是对于上面的代码,它将 passesngerData 替换为“searchedData”。我需要保留原始的 passengerData 所以我想我可以在 redux store 中创建一个新状态并从 reducer 返回它。我的问题是,我该怎么做?每次我在输入中键入内容时,整个 passengersData 数组都会消失,并且搜索不会返回任何内容。

我错过了什么?

编辑

我将添加有关处理搜索功能的组件的代码:

// imports
import { searchParamAction } from '../../screens/HomeScreen/actions/homeScreen';

class AllPassengersList extends Component {
  render() {
    const {
      searchParamActionHandler,
      searchParam,
    } = this.props;
    return (
      <View>
          <View>
            <TextInput
              onChangeText={text => searchParamActionHandler(text)}
              value={searchParam}
              placeholder="Search..."
            />
          </View>
        <Text>{searchParam}</Text>
        <PassengerCardBasedOnRoute searchParam={searchParam} />
      </View>
    );
  }
}

AllPassengersList.propTypes = {
  passengersData: PropTypes.oneOfType([PropTypes.array]).isRequired,
  searchParam: PropTypes.oneOfType([PropTypes.string]).isRequired,
  searchParamActionHandler: PropTypes.oneOfType([PropTypes.func]).isRequired,
};

export default compose(
  connect(
    store => ({
      navigationStore: store.homeScreen.navigation,
      searchParam: store.homeScreen.searchParam,
      passengersData: store.homeScreen.passengersData,
    }),
    dispatch => ({
      searchParamActionHandler: value => {
        dispatch(searchParamAction(value));
      },
    }),
  ),
)(AllPassengersList);

上面的组件是保存搜索文本输入的组件。 下面的那个是我渲染需要过滤的对象数组的那个:

import { View } from 'react-native';
import React from 'react';
import PropTypes from 'prop-types';
import { compose } from 'redux';
import { connect } from 'react-redux';
import PassengersInfo from './PassengerInfo';

import { popupsModalsAction } from '../PopupsModals/actions/popupsModals';

const PassengerCardBasedOnRoute = ({
  navigationStore,
  passengersData,
  popupsModalsActionHandler,
  searchParam,
}) => {
  return (
      <View>
        {passengersData.map(info => (
            <PassengersInfo
              key={info.id}
              id={info.id}
              searchParam={searchParam}
              cardinalpoint={info.cardinalpoint}
              name={info.name}
              address={info.address}
              datetime={info.timestamp}
            />
          ))}
      </View>
  );
};

PassengerCardBasedOnRoute.propTypes = {
  passengersData: PropTypes.oneOfType([PropTypes.array]).isRequired,
  searchParam: PropTypes.oneOfType([PropTypes.string]).isRequired,
};

export default compose(
  connect(
    store => ({
      passengersData: store.homeScreen.passengersData,
      searchParam: store.homeScreen.searchParam,
    }),
  ),
)(PassengerCardBasedOnRoute);

所以 passengersData 是处理我需要的数据的数组。

最佳答案

您不应该在 redux store 中过滤数据并将结果分配给您从中过滤数据的变量,因为这样在每次搜索时您都会丢失原始数据,而只是将 searchParam 存储在 store并编写一个返回筛选结果的选择器并在组件中使用它

const filterSelector = (state, props) => {
    return state.passengersData.filter((passenger) => passenger.name === state.searchParam);
}

const mapStateToProps = (state, props) => {
   const searchData = filterSelector(state, props);
   return {
       searchData
   }
}

你的 reducer 就是

[ActionTypes.SEARCH_PARAM](state, action) {
       return {
         ...state,
         searchParam: action.payload.searchParam,
       };
    }

编辑:用例子更新代码

// imports
import { searchParamAction } from '../../screens/HomeScreen/actions/homeScreen';

class AllPassengersList extends Component {
  render() {
    const {
      searchParamActionHandler,
      searchParam,
    } = this.props;
    return (
      <View>
          <View>
            <TextInput
              onChangeText={text => searchParamActionHandler(text)}
              value={searchParam}
              placeholder="Search..."
            />
          </View>
        <Text>{searchParam}</Text>
        <PassengerCardBasedOnRoute searchParam={searchParam} />
      </View>
    );
  }
}

AllPassengersList.propTypes = {
  passengersData: PropTypes.oneOfType([PropTypes.array]).isRequired,
  searchParam: PropTypes.oneOfType([PropTypes.string]).isRequired,
  searchParamActionHandler: PropTypes.oneOfType([PropTypes.func]).isRequired,
};

const filterSelector = (passengersData, searchParam) => {
     return passengersData.filter((passenger) => searchParams == '' || passenger.name === searchParam);
}

const mapStateToProps = store => ({
      navigationStore: store.homeScreen.navigation,
      searchParam: store.homeScreen.searchParam,
      passengersData: filterSelector(state.homeScreen.passengersData, state.homeScreen.searchParam),
}),
export default compose(
  connect(

    dispatch => ({
      searchParamActionHandler: value => {
        dispatch(searchParamAction(value));
      },
    }),
  ),
)(AllPassengersList);
,

关于javascript - 如何使用 Redux 过滤数据但保持旧状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54831679/

相关文章:

javascript - Unslider.js 中的变量递增但未显式递增

javascript - 如何将列表项的名称传递给另一个组件?

javascript - 如何从 onclick 调用 ES6 模块函数

javascript - 使用带有 Typescript 的 Leaflet map,无法在模块内导入 Leaflet

node.js - ESLint 规则在用户模块和标准 Node 模块之间插入一个空行

javascript - 在 Protractor/E2E 测试中访问 $http 数据 (AngularJS)

javascript - 使用按钮的值而不是它的 id 通过 JavaScript 模拟按钮点击?

javascript - facebook js sdk。如何在用户没有实际登录 Facebook 的情况下登录 Facebook?

javascript - 如何修复元素类型无效 : expected a string (for built-in components)?

ReactJS 事件 - this.props.onSubmit(this.state....)