Redux 商店不会在第一次单击按钮时更新
Posted
技术标签:
【中文标题】Redux 商店不会在第一次单击按钮时更新【英文标题】:Redux store doesn't update on first button click 【发布时间】:2019-11-27 03:57:19 【问题描述】:我想使用 redux,但仍然通过我的本地状态控制在 bootstrap-react-table 中呈现的内容。因此,在 componentDidMount 中,我正在获取我的数据,当我尝试通过按钮进行过滤时,单击我将 setState 设置为名为“itemsToDisplay”的字段,然后我想将其用作表中的数据。但是点击只在第二次起作用,当我在 render/componentDidMount 中记录状态时,它是未定义的。
我尝试了不同的条件来呈现表格的数据字段道具中的项目,但没有成功。我也尝试在 componentWillMount 中设置状态。
class Deliveries extends Component
constructor(props)
super(props);
this.state =
itemsToDisplay: this.props.deliveries,
;
componentDidMount()
this.props.getDeliveries();
this.setState(prev =>
return
...prev,
itemsToDisplay: this.props.deliveries,
)
filterUndelivered = () =>
this.props.filterUndelivered();
this.setState(prev =>
return
...prev,
itemsToDisplay: this.props.undelivered_items,
)
;
getFilters = () =>
return (
<div>
<Button className="m-1" color="primary">By time</Button>
<Button className="m-1" color="primary" onClick= this.filterUndelivered >Not delivered</Button>
</div>
);
;
render()
const itemsToDisplay = this.state;
const options =
insertBtn: this.createCustomInsertButton,
searchField: this.createCustomSearchField,
;
return (
<div className="animated fadeIn">
<div className="d-flex justify-content-between">
<div className="font-weight-bold mt-2">Deliveries Monitor</div>
<div className="d-flex justify-content-end">
this.getFilters()
</div>
</div>
<BootstrapTable
data= itemsToDisplay ? itemsToDisplay : this.props.deliveries
version="4"
search
hover
pagination
bordered=false
headerStyle= background: "#20a8d8"
bodyStyle= cursor: "pointer"
options= options
>
<TableHeaderColumn isKey dataField="delivery_id">Delivery#</TableHeaderColumn>
<TableHeaderColumn dataField="seller">Seller</TableHeaderColumn>
<TableHeaderColumn dataField="address">Address</TableHeaderColumn>
<TableHeaderColumn dataField="site">Site</TableHeaderColumn>
<TableHeaderColumn dataField="end_of_window">End of window</TableHeaderColumn>
<TableHeaderColumn dataField="due_date">Due date</TableHeaderColumn>
<TableHeaderColumn dataField="status">Status</TableHeaderColumn>
</BootstrapTable>
</div>
)
const mapStateToProps = state =>
return
deliveries: state.deliveriesReducer.deliveries,
undelivered_items: state.deliveriesReducer.undelivered_items,
;
const mapDispatchToProps = (dispatch) =>
return bindActionCreators( getDeliveries, filterUndelivered , dispatch);
;
export default connect(mapStateToProps, mapDispatchToProps)(Deliveries);
当数据道具的条件正确时,预期的结果是能够在第一次点击时进行过滤。
【问题讨论】:
我过去也遇到过同样的问题。你检查过 Redux 的数据流吗? 我做到了。从操作到从减速器返回的所有过程中,数据看起来都很好,并且组件可以正确接收它。出于某种原因,第一次单击将“itemsToDisplay”保留为未定义,然后在第二次单击时正常工作。 有没有可能是同步问题? 尝试使用 componentWillReceiveProps(nextProps) 【参考方案1】:试试这个,可能会有帮助
...
componentDidMount()
this.props.getDeliveries();
...
componentWillReceiveProps(recievedProps)
if (this.props.deliveries != recievedProps.deliveries)
this.setState(
itemsToDisplay: recievedProps.deliveries
)
...
【讨论】:
【参考方案2】:为什么您的组件中有另一个事实来源(状态)?基本上,将 props 存储在组件状态中是一种不好的做法(当然有一些情况,但我认为您在这里不需要它)。
我认为您的组件应该只接收一个 items
属性,它会显示已交付或未交付的项目。您的操作将负责根据您在 getDeliveries/filterUndelivered 操作中设置的某种过滤器在您的 items
属性中传递已交付或未交付的项目。
这样,您将始终将 items
道具传递给您的 BootstrapTable
data
道具,并且您的 redux 将负责在您的组件 items
道具中传递正确的项目(已交付或未交付)。
这种方法的另一个优点是,如果您要为您的项目添加另一种过滤器(比如说搜索查询),那么您只需扩展您的 redux 过滤器状态并添加 searchQuery
属性。这样您就可以轻松地将新过滤器应用于您的项目,并且您的组件基本上不需要任何更改。
Here 是一个简单的待办事项示例,具有简单的过滤功能,您可以将其应用于您的案例。
【讨论】:
【参考方案3】:在将数据加载到表之前执行简单的检查数据是否可用
itemsToDisplay.lenght > 0 &&
<BootstrapTable
data= itemsToDisplay
version="4"
search
hover
pagination
bordered=false
headerStyle= background: "#20a8d8"
bodyStyle= cursor: "pointer"
options= options
>
<TableHeaderColumn isKey dataField="delivery_id">Delivery#</TableHeaderColumn>
<TableHeaderColumn dataField="seller">Seller</TableHeaderColumn>
<TableHeaderColumn dataField="address">Address</TableHeaderColumn>
<TableHeaderColumn dataField="site">Site</TableHeaderColumn>
<TableHeaderColumn dataField="end_of_window">End of window</TableHeaderColumn>
<TableHeaderColumn dataField="due_date">Due date</TableHeaderColumn>
<TableHeaderColumn dataField="status">Status</TableHeaderColumn>
</BootstrapTable>
【讨论】:
【参考方案4】:尝试修改您的代码,如下所示:
filterUndelivered = () =>
this.props.filterUndelivered();
;
componentWillReceiveProps = nextProps =>
if (nextProps.undelivered_items !== undefined)
this.setState( itemsToDisplay: nextProps.undelivered_items );
;
同时在浏览器中安装 Redux 开发工具并分析应用程序状态。它可能会让您更深入地了解问题。
铬:https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd
火狐:https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/
【讨论】:
我试过了,逻辑还是一样:第一次点击不行,第二次点击有效。 您是否厌倦了开发工具...您是否在状态下看到第一次点击的数据? 是的,在 Redux devtools 中,状态会在第一次单击和 store 正确更新后发生变化。 第一次点击时在componentWillReceiveProps中获得回调?..添加一些控制台日志并查看 实际上,我设法通过@prasobh.kollattu 的回答解决了这个问题,但请注意,setState 函数还需要一个传播才能准确地了解先前的状态:componentWillReceiveProps = nextProps => if (nextProps.undelivered_items !== undefined) this.setState(prev => return ...prev, itemsToDisplay: nextProps.undelivered_items ); ;
以上是关于Redux 商店不会在第一次单击按钮时更新的主要内容,如果未能解决你的问题,请参考以下文章