Redux/React - 搜索字段不会立即更新 redux 状态

IT技术 search reactjs state redux
2021-04-29 17:26:47

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

我的 Actioncreator 非常简单(只返回传递给它的术语):

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。看起来状态没有更新。

3个回答

这个答案增加了Aniket Nandan指出的一点——你在 React 组件内部使用 setState 而不是依赖于上面的 props。

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

使用状态容器(它总是让我想起使用状态机)使您可以构建您的应用程序,而无需通过树向下传递回调以使更改返回顶部。相反,Redux 处理 state 的更改,并通过 props 将所有内容交还给 React。

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

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

更进一步,如果您connect正确使用(from react-redux),那么您应该可以使用 Redux 存储中的 dispatch 方法(这通过上下文发生)。

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

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

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

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

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

}

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

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

这实际上是 Redux 如此出色的原因之一——它提供了一种方法来确保根据自己容器内的用户操作正确更新状态,以便您可以保证应用程序中的所有内容都是同步的。

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

因此,您应该坚持只使用 Redux 存储中的 dispatch 方法,并允许 Redux 通过其工作流处理状态更新,并允许状态通过 props 向下流动到组件。遵守此流程将防止可能发生的许多这些奇怪的“状态不同步”类型的问题。

实际上它与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也照顾到这一点。您可能会认为,如果状态没有在我们更新后立即更新,那么我该如何处理。但 React 是个好孩子……如果你调用一个函数来更新一个状态,然后你调用另一个函数来处理上次更新的状态,那么你可以使用它。

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

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

我找到了解决方案。 React - State not updated 看起来 setState 实际上并没有立即设置状态。所以我改用了回调函数。

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

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