Подключите панель поиска и компоненты результатов поиска к глобальному состоянию - PullRequest
1 голос
/ 13 января 2020

Я новичок в ReactJS, и недавно я придумал этот редукционный магазин дат, который в основном использует реакции. Я пытаюсь иметь хороший gr asp на нем.

Только для целей понимания, у меня есть Массив объектов, хранящихся в магазине в состоянии c на данный момент.

вот так:

const initialState = {


jsonData: [
    {
     "id": "1",
     "country": "India",
     "state": "Andhra_Pradesh",
     "city": "Amaravati",
     "station": "Secretariat, Amaravati - APPCB",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "PM2.5",
     "pollutant_min": "62",
     "pollutant_max": "278",
     "pollutant_avg": "139",
     "pollutant_unit": "NA"
   },
   {
     "id": "2",
     "country": "India",
     "state": "Andhra_Pradesh",
     "city": "Amaravati",
     "station": "Secretariat, Amaravati - APPCB",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "PM10",
     "pollutant_min": "74",
     "pollutant_max": "136",
     "pollutant_avg": "104",
     "pollutant_unit": "NA"
   },
   {
     "id": "149",
     "country": "India",
     "state": "Delhi",
     "city": "Delhi",
     "station": "Lodhi Road, Delhi - IMD",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "NO2",
     "pollutant_min": "NA",
     "pollutant_max": "NA",
     "pollutant_avg": "NA",
     "pollutant_unit": "NA"
   },
   {
     "id": "150",
     "country": "India",
     "state": "Delhi",
     "city": "Delhi",
     "station": "Lodhi Road, Delhi - IMD",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "CO",
     "pollutant_min": "34",
     "pollutant_max": "117",
     "pollutant_avg": "57",
     "pollutant_unit": "NA"
   },
]

Я пытаюсь создать действие вот так:

  { 
    type: "SEARCH",
    payload: {
      pattern: 'Mah'
    } 
  }

и отправляю это действие. и пытается отфильтровать магазин на основе шаблона. Я беру образец и преобразовываю его как RegExp. и использование тестовой функции для фильтрации данных.

Но почему-то это не работает, данные не фильтруются с помощью RegExp. Я получаю то же состояние даже после фильтрации данных. Я не могу понять, в чем проблема:

Вот полный код:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './App';
import './index.css';

const initialState = {
  jsonData: [
    {
     "id": "1",
     "country": "India",
     "state": "Andhra_Pradesh",
     "city": "Amaravati",
     "station": "Secretariat, Amaravati - APPCB",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "PM2.5",
     "pollutant_min": "62",
     "pollutant_max": "278",
     "pollutant_avg": "139",
     "pollutant_unit": "NA"
   },
   {
     "id": "2",
     "country": "India",
     "state": "Andhra_Pradesh",
     "city": "Amaravati",
     "station": "Secretariat, Amaravati - APPCB",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "PM10",
     "pollutant_min": "74",
     "pollutant_max": "136",
     "pollutant_avg": "104",
     "pollutant_unit": "NA"
   },
   {
     "id": "149",
     "country": "India",
     "state": "Delhi",
     "city": "Delhi",
     "station": "Lodhi Road, Delhi - IMD",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "NO2",
     "pollutant_min": "NA",
     "pollutant_max": "NA",
     "pollutant_avg": "NA",
     "pollutant_unit": "NA"
   },
   {
     "id": "150",
     "country": "India",
     "state": "Delhi",
     "city": "Delhi",
     "station": "Lodhi Road, Delhi - IMD",
     "last_update": "18-12-2019 09:00:00",
     "pollutant_id": "CO",
     "pollutant_min": "34",
     "pollutant_max": "117",
     "pollutant_avg": "57",
     "pollutant_unit": "NA"
   },

  ]
};

function reducer(state = initialState, action) {
  console.log('reducer', state, action); 

  switch(action.type) {
    case 'SEARCH':      
      const updatedPattern =  new RegExp(action.payload.pattern)
      return {
        jsonData: initialState.jsonData.filter(item => updatedPattern.test(item.state))
      };

    default:
      return state;
  }
}

function getState() {
  console.log(initialState.jsonData);
}

const store = createStore(reducer);

store.dispatch(
  { 
    type: "SEARCH",
    payload: {
      pattern: 'And'
    } 
  }
);
getState();



ReactDOM.render(  
  <Provider store={store}>    
    <App />
  </Provider>
  ,
  document.getElementById('root')
);

Ответы [ 2 ]

1 голос
/ 13 января 2020

Поскольку подход ОП и принятый ответ имеют несколько критических значений fl aws, позвольте мне поделиться моими предложениями:

  • вы не хотите заменять исходный массив в своем текущем состояние с его отфильтрованной копией - если вы набрали Mah в строке поиска и всего одну секунду спустя решили искать elh, вы можете получить пустые результаты поиска, если в ранее отфильтрованном массиве не было совпадений (в то время как исходный );
  • использование RegExp test() для базового c частичного совпадения без учета регистра является абсолютным перебором, есть гораздо менее дорогой вариант, основанный на Array.prototype.includes() вместе с Array.prototype.some() при необходимости (например, вы можете ссылаться на живой фрагмент внизу);
  • оба ранее опубликованных решения предлагают использовать шаблон subscribe... store.dispatch() для доступа к глобально хранимым переменным состояния, которые не рекомендуется

Если вам действительно нужно хранить результаты поиска в глобальном состоянии, и вы хотите получить их через следует использовать соответствующее действие (например, SEARCH) и доступ к глобальному searchResults в методе произвольного компонента connect() в сочетании с mapDispatchToProps() и mapStateToProps() соответственно.

Вы можете найти демо-версию ниже:

//dependencies
const { render } = ReactDOM,
      { createStore } = Redux,
      { connect, Provider } = ReactRedux
      
//search action, initial state, reducer, store
const SEARCH = 'SEARCH',
      initialState = {jsonData:[{"id":"1","country":"India","state":"Andhra_Pradesh","city":"Amaravati","station":"Secretariat, Amaravati - APPCB","last_update":"18-12-2019 09:00:00","pollutant_id":"PM2.5","pollutant_min":"62","pollutant_max":"278","pollutant_avg":"139","pollutant_unit":"NA"},{"id":"2","country":"India","state":"Andhra_Pradesh","city":"Amaravati","station":"Secretariat, Amaravati - APPCB","last_update":"18-12-2019 09:00:00","pollutant_id":"PM10","pollutant_min":"74","pollutant_max":"136","pollutant_avg":"104","pollutant_unit":"NA"},{"id":"149","country":"India","state":"Delhi","city":"Delhi","station":"Lodhi Road, Delhi - IMD","last_update":"18-12-2019 09:00:00","pollutant_id":"NO2","pollutant_min":"NA","pollutant_max":"NA","pollutant_avg":"NA","pollutant_unit":"NA"},{"id":"150","country":"India","state":"Delhi","city":"Delhi","station":"Lodhi Road, Delhi - IMD","last_update":"18-12-2019 09:00:00","pollutant_id":"CO","pollutant_min":"34","pollutant_max":"117","pollutant_avg":"57","pollutant_unit":"NA"}], searchResult:[]},
      appReducer = (state=initialState, action) => {
        switch(action.type){
          case SEARCH : {
            const {jsonData} = state,
                  {searchedString} = action,
                  searchResult = searchedString.length ? 
                    jsonData.filter(item => 
                      Object.values(item).some(val =>
                        val
                          .toLowerCase()
                          .includes(searchedString.toLowerCase()))) :
                    []
            return {...state, searchResult}
          }
          default: return state
        }
      },
      store = createStore(appReducer)

//searchbar ui component
const SearchBar = ({searchResults}) => (
  <input onKeyUp={e => searchResults(e.target.value)} />
)

//connect searchbar component's searchResult prop to dispatching SEARCH action
const mapDispatchToProps = dispatch => ({
        searchResults: val => dispatch({type: SEARCH, searchedString: val})
      }),
      SearchBarContainer = connect(null, mapDispatchToProps)(SearchBar)
      
//search results ui component
const SearchResults = ({results}) => (
  <div>
    {results.map(item => <div>{JSON.stringify(item)}</div>)}
  </div>
)
//connect global state searchResult to component's results
const mapStateToProps = ({searchResult:results}) => ({results}),
      SearchResultsContainer = connect(mapStateToProps)(SearchResults)
      
//global Povider wrapper
render (
  <Provider {...{store}}>
    <SearchBarContainer />
    <SearchResultsContainer />
  </Provider>,
  document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.3/react-redux.min.js"></script><div id="root"></div>
1 голос
/ 13 января 2020

1. Вам следует изменить функцию отображения вашего магазина, которая всегда записывает исходные данные

Может быть, вы можете изменить это, чтобы увидеть изменение магазина:

function getState() {
  console.log(store.getState());
}

Просто console.log(initialState.jsonData); всегда показывает исходные данные.

2. reducer функция всегда должна менять текущее состояние

function reducer(state = initialState, action) {
  console.log('reducer', state, action); 

  switch(action.type) {
    case 'SEARCH':      
      const updatedPattern =  new RegExp(action.payload.pattern)
      return {
        jsonData: state.jsonData.filter(item => updatedPattern.test(item.state))
      };

    default:
      return state;
  }
}

Смена ключа происходит после: jsonData: state.jsonData.filter(item => updatedPattern.test(item.state))

3. Возможно, вы можете использовать store.subscribe(handleChange), чтобы получить изменение магазина

const unsubscribe = store.subscribe(getState)

использовать store.subscribe для автоматического получения действия изменения состояния, как react-redux делает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...