reducer 中的状态更改后组件不会重新渲染
Component isn't re-rendering after state change in reducer
假设我有一个 link,单击它时,它会向我的状态对象中名为 queue
的数组添加一个随机数。整个 state.queue 数组显示在我的页面上,并在我们单击 link 时更新。我目前有一个 link 应该做类似的事情但是在我的减速器改变状态(向数组添加一个新项目)之后,我的页面没有(重新?)呈现我的组件等等页面不更新。
我应该怎么做才能在我的页面上显示整个 state.queue,包括在我单击 link 时动态更新?这是我拥有的:
Channel.js
class Channel extends Component {
constructor(props) {
super(props);
this.state = {
queue: [],
// more initializations
};
...
}
...
render() {
return (
<div>
{/*This part is never called because this.state.queue never has anything in it! */}
{this.state.queue &&
this.state.queue.length > 0 &&
<div>
<ul>
{this.state.queue.map((queuedItem, i) =>
<li key={i}>{queuedItem}</li>
)}
</ul>
</div>}
<div>
<QResults
allQueryResults={this.state.queryState}
requestHandler={queueNewRequest}
/>
</div>
</div>
);
}
}
function mapStateToProps(state) {
const{queue} = state
return {queue}
}
function mapDispatchToProps(dispatch) {
return ({
queueNewRequest: (newRequestData) => { dispatch({type: newRequestData}) }
})
}
export default withRouter(connect(mapStateToProps , mapDispatchToProps )(Channel))
QResults.js
export default class QResults extends Component {
render() {
const {requestHandler} = this.props
return (
<ul>
{this.props.allQueryResults.items.map((trackAlbum, i) =>
<li key={i}>
<a href='#'
onClick={
() => requestHandler(trackAlbum.name)}>
Some link
</a>
</li>
)}
</ul>
)
}
}
actions.js
export const QUEUE_NEW_REQUEST = 'QUEUE_NEW_REQUEST'
export function queueNewRequest(newRequestInfo) {
return dispatch => {
dispatch({
type: QUEUE_NEW_REQUEST,
payload: newRequestInfo
})
}
}
reducers.js
import { combineReducers } from 'redux'
function reducer1(state = {}, action) {
...
}
function reducer2(state = {}, action) {
switch (action.type) {
case QUEUE_NEW_REQUEST:
return {
...state,
/*queue: [...state.queue,action.payload],*/ //compiler complains that 'TypeError: state.queue is not iterable'
queue:[action.payload]
}
default:
return state
}
}
const rootReducer = combineReducers({
reducer1,
reducer2
})
export default rootReducer
this.state.queue
指的是 Channel
组件的本地状态。它不是 redux 状态。您将 this.state.queue
初始化为一个空数组,然后您永远不会更改它(即,您永远不会调用 this.setState
)。
如果你想在 redux 中与状态交互,这就是 mapStateToProps 的用武之地。因为你有一个看起来像这样的 mapStateToProps:
function mapStateToProps(state) {
const{queue} = state
return {queue}
}
Channel组件会得到一个prop命名的队列,你可以通过这个.props.queue与之交互。
因此,解决方法是更新频道以与道具互动。您很可能想要删除 this.state.queue,因为它似乎没有任何用处,而且由于其名称而引起混淆。
{this.props.queue &&
this.props.queue.length > 0 &&
<div>
<ul>
{this.state.queue.map((queuedItem, i) =>
<li key={i}>{queuedItem}</li>
)}
</ul>
</div>
}
此外,您设置根减速器的方式让您的 redux 状态看起来像这样:
{
reducer1: {}, // not sure what this contains, since reducer 1 was omitted
reducer2: {
queue: [],
}
}
因此,如果这真的是您希望 redux 状态看起来像的样子,您的 props 映射状态将需要更新为:
function mapStateToProps(state) {
const {queue} = state.reducer2;
return {queue};
}
使用 connect
将 state
对象连接到 props
后,您将在 props
中获得返回的对象。看到这个:https://react-redux.js.org/using-react-redux/connect-mapstate#return.
因此,您只需将 Channel.js
文件中的 this.state.queue
更改为 this.props.queue
。
并且您的组件未呈现,因为它不依赖于已更改的 props
。因此,进行 above-suggested 更改应该可以解决问题。
除了关于将 this.state.queue
更改为 this.props.queue
的所有回复之外,我还需要做一些事情。在我的 reducer2
:
中初始化队列
function reducer2(state = {queue:[]}, action) {
switch (action.type) {
case QUEUE_NEW_REQUEST:
return {
...state,
queue: [...state.queue,action.payload],
}
default:
return state
}
}
更改 Channel.js 中的 mapStateToProps:
function mapStateToProps(state) {
const{queue} = state.reducer2
return {queue}
}
假设我有一个 link,单击它时,它会向我的状态对象中名为 queue
的数组添加一个随机数。整个 state.queue 数组显示在我的页面上,并在我们单击 link 时更新。我目前有一个 link 应该做类似的事情但是在我的减速器改变状态(向数组添加一个新项目)之后,我的页面没有(重新?)呈现我的组件等等页面不更新。
我应该怎么做才能在我的页面上显示整个 state.queue,包括在我单击 link 时动态更新?这是我拥有的:
Channel.js
class Channel extends Component {
constructor(props) {
super(props);
this.state = {
queue: [],
// more initializations
};
...
}
...
render() {
return (
<div>
{/*This part is never called because this.state.queue never has anything in it! */}
{this.state.queue &&
this.state.queue.length > 0 &&
<div>
<ul>
{this.state.queue.map((queuedItem, i) =>
<li key={i}>{queuedItem}</li>
)}
</ul>
</div>}
<div>
<QResults
allQueryResults={this.state.queryState}
requestHandler={queueNewRequest}
/>
</div>
</div>
);
}
}
function mapStateToProps(state) {
const{queue} = state
return {queue}
}
function mapDispatchToProps(dispatch) {
return ({
queueNewRequest: (newRequestData) => { dispatch({type: newRequestData}) }
})
}
export default withRouter(connect(mapStateToProps , mapDispatchToProps )(Channel))
QResults.js
export default class QResults extends Component {
render() {
const {requestHandler} = this.props
return (
<ul>
{this.props.allQueryResults.items.map((trackAlbum, i) =>
<li key={i}>
<a href='#'
onClick={
() => requestHandler(trackAlbum.name)}>
Some link
</a>
</li>
)}
</ul>
)
}
}
actions.js
export const QUEUE_NEW_REQUEST = 'QUEUE_NEW_REQUEST'
export function queueNewRequest(newRequestInfo) {
return dispatch => {
dispatch({
type: QUEUE_NEW_REQUEST,
payload: newRequestInfo
})
}
}
reducers.js
import { combineReducers } from 'redux'
function reducer1(state = {}, action) {
...
}
function reducer2(state = {}, action) {
switch (action.type) {
case QUEUE_NEW_REQUEST:
return {
...state,
/*queue: [...state.queue,action.payload],*/ //compiler complains that 'TypeError: state.queue is not iterable'
queue:[action.payload]
}
default:
return state
}
}
const rootReducer = combineReducers({
reducer1,
reducer2
})
export default rootReducer
this.state.queue
指的是 Channel
组件的本地状态。它不是 redux 状态。您将 this.state.queue
初始化为一个空数组,然后您永远不会更改它(即,您永远不会调用 this.setState
)。
如果你想在 redux 中与状态交互,这就是 mapStateToProps 的用武之地。因为你有一个看起来像这样的 mapStateToProps:
function mapStateToProps(state) {
const{queue} = state
return {queue}
}
Channel组件会得到一个prop命名的队列,你可以通过这个.props.queue与之交互。
因此,解决方法是更新频道以与道具互动。您很可能想要删除 this.state.queue,因为它似乎没有任何用处,而且由于其名称而引起混淆。
{this.props.queue &&
this.props.queue.length > 0 &&
<div>
<ul>
{this.state.queue.map((queuedItem, i) =>
<li key={i}>{queuedItem}</li>
)}
</ul>
</div>
}
此外,您设置根减速器的方式让您的 redux 状态看起来像这样:
{
reducer1: {}, // not sure what this contains, since reducer 1 was omitted
reducer2: {
queue: [],
}
}
因此,如果这真的是您希望 redux 状态看起来像的样子,您的 props 映射状态将需要更新为:
function mapStateToProps(state) {
const {queue} = state.reducer2;
return {queue};
}
使用 connect
将 state
对象连接到 props
后,您将在 props
中获得返回的对象。看到这个:https://react-redux.js.org/using-react-redux/connect-mapstate#return.
因此,您只需将 Channel.js
文件中的 this.state.queue
更改为 this.props.queue
。
并且您的组件未呈现,因为它不依赖于已更改的 props
。因此,进行 above-suggested 更改应该可以解决问题。
除了关于将 this.state.queue
更改为 this.props.queue
的所有回复之外,我还需要做一些事情。在我的 reducer2
:
function reducer2(state = {queue:[]}, action) {
switch (action.type) {
case QUEUE_NEW_REQUEST:
return {
...state,
queue: [...state.queue,action.payload],
}
default:
return state
}
}
更改 Channel.js 中的 mapStateToProps:
function mapStateToProps(state) {
const{queue} = state.reducer2
return {queue}
}