【问题标题】:How can I filter data using Redux but keeping the old state?如何使用 Redux 过滤数据但保持旧状态?
【发布时间】:2019-07-16 19:39:31
【问题描述】:

我正在使用 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 },
});

减速器:

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 是处理我需要的数据的数组。

【问题讨论】:

    标签: javascript reactjs ecmascript-6 redux react-redux


    【解决方案1】:

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

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

    你的减速器只是

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

    【讨论】:

    • 嗨,@Shubham Khatri。我刚刚更新了我的代码。请参阅编辑部分。我回答的第一部分不太好,所以我无法适应我的代码。感谢您的帮助。
    • @Reacting 我的意思是,您不应该在商店中搜索时覆盖乘客数据,而是编写一个过滤器函数来返回过滤后的数据。更新了答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 2018-12-10
    相关资源
    最近更新 更多