Redux: mapStateToProps не вызывается - PullRequest
0 голосов
/ 17 марта 2020

Я понимаю, что этот вопрос уже задавался несколько раз здесь, в StackOverflow. Но я перепробовал все рекомендуемые решения, и у меня ничего не работает. У меня заканчиваются идеи.

Проблема в приложении React Native для Android. По сути, приложение предоставляет панель поиска для поиска в основной базе данных. Результаты поиска должны быть помещены в магазин.

Я использую Redux v4.0.5, React-Redux v7.1.3, React v16.12.0 и React Native v0.61.5. Для отладки я использую React Native Debugger в последней версии.

Теперь упрощенный код. Сначала компонент с панелью поиска. Здесь mapStateToProps() называется. Пользователь вводит данные и useEffect() немедленно запускает запрос к базе данных, что должно привести к немедленному вызову mapStateToProps().

import React, {useEffect, useRef, useState} from 'react';
import {connect} from 'react-redux';    
import {RootState} from '../../../rootReducer/rootReducer';
import {setResultValueSearchBar} from '../../../store/searchBar/actions';
imports ...

type Props = {};

const SearchBar: React.FC<Props> = () => {
  const [returnValue, setReturnValue] = useState('');
  const [inputValue, setInputValue] = useState('');

  useEffect(() => {
    // get query results
    // logic to finally get a result string that should be put into the store
    const resultNames: string = resultNamesArray.toString();

    // method to set local and Redux state
    const sendReturnValueToReduxStore = (resultNames: string) => {
      setReturnValue(resultNames);
      setResultValueSearchBar({resultValue: resultNames});
      console.log('result value sent to store ', resultNames);
    };

    // call above method
    sendReturnValueToReduxStore(resultNames);
  }, [inputValue, returnValue]);

  return (
    <View>
      <ScrollView>
        <Header searchBar>
          <Item>
            <Input
              placeholder="Search"
              onChangeText={text => setInputValue(text)}
              value={inputValue}
            />
          </Item>
        </Header>
      </ScrollView>
    </View>
  );
};

function mapStateToProps(state: RootState) {
  console.log("map state to props!", state); // is only called one time, initially
  return {
    resultValue: state.searchBarResult.resultValue,
  };
}

const mapDispatchToProps = {
  setResultValueSearchBar,
};

export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);

Вот здесь rootReducer:

import {combineReducers} from 'redux';

import searchBarResultReducer from '../store/searchBar/reducers';
import reducer2 from '../store/reducer2example/reducers';

const rootReducer = combineReducers({
  searchBarResult: searchBarResultReducer,
  reducer2Result: reducer2,
});

export type RootState = ReturnType<typeof rootReducer>;

Здесь это searchBarResultReducer в reducers.ts файле:

import {
  SearchBarResultState,
  SET_RESULT_VALUE_SEARCHBAR,
  ResultValueType,
} from './types';

const initialState: SearchBarResultState = {
  resultValue: 'No results',
};

// take state and action and then return a new state
function searchBarResultReducer(
  state = initialState,
  action: ResultValueType,
): SearchBarResultState {
  console.log('invoked result: ', action.type); // called only initially
  if (action.type === 'SET_RESULT_VALUE_SEARCHBAR') {
    return {
      ...state,
      ...action.payload,
    };
  } else {
    return state;
  }
}

export default searchBarResultReducer;

и соответствующем types.ts ...

export const SET_RESULT_VALUE_SEARCHBAR = 'SET_RESULT_VALUE_SEARCHBAR';

export interface SearchBarResultState {
  resultValue: string;
}

interface ResultValueAction {
  type: typeof SET_RESULT_VALUE_SEARCHBAR;
  payload: SearchBarResultState;
}

export type ResultValueType = ResultValueAction

... и actions.ts:

import {SET_RESULT_VALUE_SEARCHBAR, ResultValueType, SearchBarResultState} from './types'

export const setResultValueSearchBar = (resultValue: SearchBarResultState): ResultValueType => ({
  type: SET_RESULT_VALUE_SEARCHBAR,
  payload: resultValue,
});

И index.js:

import React from 'react';
import {AppRegistry} from 'react-native';
import {createStore, applyMiddleware, compose} from 'redux';
import {Provider} from 'react-redux';
import App from './App';
import {name as appName} from './app.json';
import rootReducer from './src/rootReducer/rootReducer';
import Realm from 'realm';
import { composeWithDevTools } from 'redux-devtools-extension';
import invariant from 'redux-immutable-state-invariant';

const composeEnhancers = composeWithDevTools({});
const store = createStore(
  rootReducer, 
  composeEnhancers(applyMiddleware(invariant()))
  );

const Root = () => {
  Realm.copyBundledRealmFiles();
  return (
    <Provider store={store}>
      <App />
    </Provider>
  );
};

AppRegistry.registerComponent(appName, () => Root);

Подведем итог: при успешном выполнении запроса к базе данных значение результата следует отправлять в хранилище. Но в React Native Debugger/Redux Devtools редуктор / mapStateToProps() вызывается только один раз и только так, как показано в файле console.log в коде.

Что здесь происходит?

1 Ответ

0 голосов
/ 17 марта 2020

Решено! Как заявлено Гемантом в этом потоке, вы также должны передать действие, которое вы импортируете, как реквизиты в компонент. Теперь работает как шарм :)

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