Redux/React - 搜索字段没有立即更新 redux 状态

Redux/React - Search field is not updating the redux state instantly

我是 redux 世界的新手,我正在尝试制作报纸应用程序。我目前正在研究用户可以搜索特定报纸标题的搜索功能。问题是,当我第一次输入例如 'a' 时,状态是 ''。当我键入更多例如 'b' 时,状态显示该术语是 'a' 而它应该是 'ab'。我正在使用 redux chrome 工具来检查这个全局状态。

我的Actioncreator真的很简单(只有returns传递给它的术语):

export function search(term) {
  return{
    type:SEARCH,
    term
  }
}

这里是减速器:

const SearchReducer = (state = '', action) => {

    switch (action.type) {
        case SEARCH:
            return action.term;
        default:
            return state;
    }

}

这是根减速器:

/*Application state*/
const rootReducer = combineReducers({
    weather: WeatherReducer,
    filters: FilterReducer,
    articles:ArticleReducer,
    search: SearchReducer // this should be 'ab', but is 'a' 
});

这是非常简单的设置。这是我与 redux 的通信方式。

我有我的 material-ui 文本字段(我也试过香草输入字段)

<TextField  style={style.searchWidget.search}
            floatingLabelText="Search"
            value={this.state.term}
            onChange={this._onSearchChange}
 />

当用户键入内容时,将触发 _onSearchChange 函数。

_onSearchChange(event) {
    this.setState({term: event.target.value});
    this.props.search(this.state.term);
}

这将设置此搜索组件的当前状态。然后它将调度更新全局状态的搜索操作。但不能正常工作。全局状态总是落后1步。

有什么想法吗?

编辑: 看起来不是redux而是react。组件状态不会立即更新。正确的术语被传递给 actionreducer,所以这不是 redux 的错。我尝试在设置状态后打印出this.state.term。而且看起来状态没有更新。

我找到了解决方案。 看起来 setState 实际上并不是立即设置状态。 所以我改用回调函数。

    _onSearchChange(event) {
    this.setState({term: event.target.value}, function () {
        console.log(this.state.term)
    });
    }

现在当我输入 'a' 时,它会记录 'a'!

其实和redux没有关系。您必须记住,在使用 React 时,您无法在更新 React 状态后立即获得更新状态。举个例子吧。

getInitialState: function() {
  return {
     myState: 0
  }
},

updateState: function(stateVersion) {
   console.log(this.state.myState); //this will print 0
   this.setState({ myState: stateVersion });
   console.log(this.state.myState); //this will print 0
}

现在,如果我们第一次使用状态版本作为参数调用 updateState 函数,即使我们发送 1 或 2 或任何数字作为参数,它也会为两个控制台打印 0。 假设我们发送了 2 作为参数。然后我们可以在下一次使用另一个参数调用该函数时获得该状态。 但 React 也会处理这个问题。 您可能会认为,如果状态没有在我们更新后立即更新,那么我该如何处理它。但是反应是一个好孩子...... 如果您调用一个函数来更新状态,然后调用另一个函数来处理上次更新的状态,那么您可以使用它。

我想我已经回答了你为什么不更新 redux state 的问题。

另一种想法是,当您将 redux 状态用于搜索缩减器时,那么为什么您还要处理反应状态。您可以直接将搜索到的参数传递到您的操作中。您可以立即从您的 reducer 状态中获取该更新。 它将帮助您简化代码。

这个答案对 Aniket Nandan 指出的内容做了一些补充——您在 React 组件内部使用了 setState,而不是依赖上面的 props。

使用 Redux 的主要目的是获取您的状态并将其与应用程序一起放入容器中。这样做的好处是您的状态可以在多个组件之间共享,然后您可以通过 props 将内容传递到组件树中的组件中。

状态容器的使用(它总是让我想起使用状态机)允许你构建你的应用程序,而不必通过树向下传递回调以获得更改以返回到顶端。相反,Redux 处理状态的变化,并通过 props 将一切交还给 React。

_onSearchChange(event) {
    this.setState({term: event.target.value});
    this.props.search(this.state.term);
}

关于这一点,看看上面的代码,来自您的 post,我想知道为什么您将 setState 设置为该术语,但随后总是调用您通过 props 接收的函数?然后搜索会调用 Redux 存储中的 dispatch 方法吗?如果没有,那么你没有完全正确连接。

此外,如果您正确使用了 connect(来自 react-redux),那么您应该可以使用 Redux 存储中的调度方法(这通过上下文发生)。

Redux 的设计工作方式更像是这样的:

_onSearchChange(event) {
    this.props.dispatch({ type: 'SEARCH', term: event.target.value });
}

然后会发生什么是 Redux 应该处理状态更新,并且新状态将通过 props 从 Redux 流向 React(这通过 Redux 中的所有连接发生,这非常棒!)。 =26=]

const SearchReducer = (state = '', action) => {

    switch (action.type) {
        case SEARCH:
            return action.term;
            break;
        default:
            return state;
    }

}

根据你的 reducer(复制在上面 ^^)和你对 combineReducers 的使用,如果你输入 'ab',你应该最终得到一个具有 { search: { term: 'ab' } } 的状态,并且它只输入 'a' 后应该是 'a',而不是落后。

你使用 setState 和来自 props 的方法实际发生了什么是初始状态(我假设 '')被传递给 this.props.search,第一次。同时,在您键入 'a' 后,状态正在组件上更新为 'a'。然后,下一次,当您键入 'b' 时,状态更新为 'ab',但 this.props.search 仅在 setState 完成执行之前从状态接收到术语——虽然它仍然是 'a'。

这实际上是 Redux 如此出色的原因之一——它提供了一种方法来确保状态根据其自己容器内的用户操作正确更新,这样您就可以保证所有内容在您的申请。

关于这一点,我将留下一条关于使用 Redux 的建议:你应该很少发现自己在使用 Redux 的应用程序中的 React 组件中使用 setState。何时在组件内使用 setState 取决于您要设置的状态片段是否仅存在于该组件内,而应用程序的其余部分不需要知道它。我想不出一个例子,而且我能提供的任何例子都可能很做作。就这一点而言,我想不出一个的原因是因为我认为在应用程序中有这样的用例是非常罕见的。

因此,您应该坚持仅使用 Redux store 的 dispatch 方法,并允许 Redux 通过其工作流处理状态更新,并允许状态通过 props 向下流动到组件。坚持这个流程将防止许多可能发生的奇怪 "states getting out of sync" 类型的问题。