如何使用 getState 和 redux thunk

Posted

技术标签:

【中文标题】如何使用 getState 和 redux thunk【英文标题】:How to use getState with redux thunk 【发布时间】:2018-06-03 12:46:04 【问题描述】:

我有一个名为 searchResult() 的动作创建者,它从 Firebase 获取数据,然后根据另一个名为 SearchReducer 的缩减程序(由动作创建者 searchChanged() 创建)中的一个名为“搜索”的状态对其进行过滤。代码如下所示:

 export const searchResult = () => 
    const  currentUser  = firebase.auth();
       return (dispatch, getState) => 

    firebase.database().ref(`/users/$currentUser.uid/entries`)
       .orderByChild('uid')
         .on('value', snapshot => 
          const myObj = snapshot.val();
          const  search  = getState().searching;

          const list = _.pickBy(myObj, (((value) => 
             value.make.indexOf(search) !== -1 || 
             value.model.indexOf(search) !== -1) && ((value) => 
             value.sold === false)));


             dispatch( type: SEARCH_RESULT_SUCCESS, payload: list );
     );
    ;
   ;

代码运行,但没有过滤任何内容。使用 redux 调试器,我可以看到“搜索”发生了变化。我的语法有问题吗?任何帮助,将不胜感激。这是我的其他代码:

Action Creator searchChanged():

 export const searchChanged = (text) => 
   return 
      type: SEARCH_CHANGED,
      payload: text
     ;
   ;

Reducer SearchReducer:

 import 
    SEARCH_CHANGED,
  from '../actions/types';

 const INITIAL_STATE = 
   search: '',
 ;

 export default (state = INITIAL_STATE, action) => 
   switch (action.type) 
     case SEARCH_CHANGED:
       return  ...state, search: action.payload ;
   default:
       return state;
   
  ;

searchResult() 的 Reducer 称为 EntryReducer:

import 
  SEARCH_RESULT_SUCCESS,
  ENTRY_FETCH_SUCCESS,
  SOLD_RESULT_SUCCESS
 from '../actions/types';

const INITIAL_STATE = [];


export default (state = INITIAL_STATE, action) => 
  switch (action.type) 
    case ENTRY_FETCH_SUCCESS:
      return action.payload;
    case SEARCH_RESULT_SUCCESS:
      return action.payload;
    case SOLD_RESULT_SUCCESS:
      return action.payload;
    default:
      return state;
  
;

这里是 combineReducers() 函数:

import  combineReducers  from 'redux';
import AuthReducer from './AuthReducer';
import EntryFormReducer from './EntryFormReducer';
import EntryReducer from './EntryReducer';
import SearchReducer from './SearchReducer';
import PasswordReducer from './PasswordReducer';

export default combineReducers(
  auth: AuthReducer,
  entryForm: EntryFormReducer,
  employees: EntryReducer,
  searching: SearchReducer,
  pw: PasswordReducer
);

这里是 searchChanged() 被调用的地方,然后是 searchResult():

class Search extends Component 

   //onSearchChange() is just the onChangeText binding for the text input.
   onSearchChange(text) 
     this.props.searchChanged(text);
     searchResult();
 

========================== 新编辑部分=================== =============

现在我在我的搜索组件中使用 mapDispatchToProps。但是,我仍然会遇到错误,或者在我输入搜索输入时什么也没有发生。整个组件看起来像这样(它返回一个错误,即 searchResult 不是一个函数。我从https://learn.co/lessons/map-dispatch-to-props-readme 得到我的方向):

import React,  Component  from 'react';
import  View  from 'react-native';
import  connect  from 'react-redux';
import  bindActionCreators  from 'redux';
import  Icon  from 'react-native-vector-icons';
import  searchChanged, searchResult  from '../actions';
import Card from './common/Card';
import CardSection from './common/CardSection';
import Input from './common/Input';


class Search extends Component 

  onSearchChange(text) 
    this.props.searchChanged(text);
    this.store.props.dispatch(searchResult());
  


  render() 
    return (
      <View>

       <Input
         placeholder="Search"
         onChangeText=this.onSearchChange.bind(this)
         value=this.props.search
         returnKeyType='search'
       />

       </View>
   );
  
 


 const mapStateToProps = state => 

   return 
     search: state.searching.search
    ;
  ;

const mapDispatchToProps = (dispatch) => 
  return bindActionCreators(
    searchResult: searchResult
  , dispatch);
;

export default connect(mapStateToProps,  searchChanged , mapDispatchToProps)(Search);

仅使用:

 onSearchChange(text) 
this.props.searchChanged(text);
dispatch(searchResult());

返回一个错误,即 dispatch 是一个未声明的变量。如何正确格式化此组件,以便它正确理解 mapDispatchToState?

【问题讨论】:

您是否尝试将您在班级中的操作从 searchResult() 修改为 this.props.searchResult()? 您必须致电dispatch(searchResult()) @DennisFrea 是的,我也试过了......结果相同。感谢您的建议! @Eric Guan 我在哪里调用 dispatch (searchResult())?我试图在 searchChanged() 中调用它,但我可能语法错误。具体会是什么样子?谢谢! 您在searchResult() 内调用onSearchChange 的确切位置。不要调用searchResult(),而是调用dispatch(searchResult()) 你需要导入redux store 才能访问dispatch 函数。或者,如果您使用 react-redux,请使用 mapDispatchToProps。 【参考方案1】:

来自您的应用级代码。

从'../actions/list-actions'导入searchResult;

onSearchChange(text) 
    this.props.searchResult(text);

  


const mapStateToProps = (state) => 

    return 
        yourListName: state.yourListName,
    


const mapDispatchToProps = (dispatch) => 
    return 
        searchResult: (data) => dispatch(searchResult(data)),
    


export default connect(mapStateToProps, mapDispatchToProps)(Search)

然后在行动中......

export const SEARCH_RESULT_SUCCESS = list => (
    type: 'SEARCH_RESULT_SUCCESS',
    payload: list,
);

   export const searchResult = (data) => dispatch 
    const  currentUser  = firebase.auth();
       return (dispatch, getState) => 

    firebase.database().ref(`/users/$currentUser.uid/entries`)
       .orderByChild('uid')
         .on('value', snapshot => 
          const myObj = snapshot.val();
          const  search  = getState().searching;

          const list = _.pickBy(myObj, (((value) => 
             value.make.indexOf(search) !== -1 || 
             value.model.indexOf(search) !== -1) && ((value) => 
             value.sold === false)));
        //!!!Do you filtering HERE based on the data (or search value) passed in 
            through the app level. 
        //Then dispatch the save of the newly edited list to your redux store.
        //Or based on your use case take just the article that matched, and store 
          it to a searched category in the store.  
             dispatch(SEARCH_RESULT_SUCCESS(list));
     );
    ;
   ;

;

【讨论】:

非常感谢@GavinThomas!我正在尝试为您的代码配置我的代码和特定用例,但不知道如何在上面的代码中格式化 onSearchChange() 函数。我可以查看与 mapDispatchToProps 或 mapStateToProps 相关的组件代码的所有部分吗?谢谢你,圣诞快乐! 这样更有意义吗?如果不参与项目,我无法为您编写所有内容 哇!感谢您在平安夜抽出宝贵时间!我认为这是有道理的......当我第一次开始尝试构建搜索过滤器时,我不知道 mapDispatchToProps。所以,在我的无知中,我以为我只是创建一个称为“搜索”的状态,它是由输入到搜索过滤器输入 (searchChanged()) 中的任何内容生成的。然后只需使用 getState 获取该状态并在我的操作 searchResult() 中过滤掉。但是因为每次用户输入搜索过滤器文本输入时,都需要调用 searchResult()。我什至需要 getState/searchChanged() 吗? 使用您的代码,您似乎只是将(文本)作为参数传递给 searchResult(),然后在 searchResult() 中使用 at 参数进行过滤。我会试试然后回来......圣诞快乐,非常感谢你! //您可以通过多种方式进行操作。它是开放的讨论。我仍然不确定您的数据集是什么。但是,可以说这是 1000 篇文章,而您正在按关键字搜索? databaseRef.child("Articles").queryOrdered(byChild: "body").queryEqual(toValue: text) 我会在拉下数据之前抓取用户输入到搜索firebase的整个完整的“文本”字词。当 Firebase 在他们的服务器上运行搜索(对你更好)然后保存并显示他们返回到 redux 商店的内容。

以上是关于如何使用 getState 和 redux thunk的主要内容,如果未能解决你的问题,请参考以下文章

React-Redux:getState() 不可用

下一个 redux 包装器出现无法读取未定义的属性 'getState' 的错误

相当于 rxjs 中可观察到的 redux 'getState'

redux thunk 中的 getState() 是不是会更改实际状态

Redux getState 在行动中不起作用

使用带有 getState() 的 mockStore 进行 Thuk 测试