[英]Component isn't re-rendering after state change in reducer
Let's say I have a link that, when clicked, adds a random number to an array in my state object called queue
. 假设我有一个链接,当单击该链接时,会将一个随机数添加到状态对象中称为
queue
的数组中。 The entire state.queue array is displayed on my page and gets updated as we click the link. 整个state.queue数组显示在我的页面上,并在我们单击链接时更新。 I currently have a link that is supposed to be doing something similar but after my reducer alters the state (adds a new item to the array), my page isn't (re-?)rendering my component and so the page does not update.
我当前有一个链接,该链接应该做类似的事情,但是在我的化简器更改状态(向数组中添加新项)后,我的页面没有(重新?)呈现我的组件,因此该页面不会更新。
What should I be doing to show the entirety of state.queue on my page, including dynamically updating as I click the link? 我应该怎么做才能在页面上显示整个state.queue,包括单击链接时动态更新? Here's what I have:
这是我所拥有的:
Channel.js 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 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 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 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
Once you connected the state
object to the props
with connect
you will get the returned objects in the props
. 使用
connect
将state
对象连接到props
,您将在props
获得返回的对象。 See this: https://react-redux.js.org/using-react-redux/connect-mapstate#return . 请参阅: https : //react-redux.js.org/using-react-redux/connect-mapstate#return 。
So, you just need to change this.state.queue
to this.props.queue
in your Channel.js
file. 所以,你只需要改变
this.state.queue
到this.props.queue
在Channel.js
文件。
And your component is not rendering because it's not dependent on the changed props
. 而且您的组件没有渲染,因为它不依赖于更改的
props
。 So, doing the above-suggested change should solve the issue. 因此,进行上述建议的更改应该可以解决该问题。
this.state.queue
refers to the state which is local to your Channel
component. this.state.queue
指Channel
组件本地的状态。 It is not the redux state. 它不是redux状态。 You initialize
this.state.queue
to an empty array, and then you never change it (ie, you never call this.setState
). 您可以将
this.state.queue
初始化为一个空数组,然后再不对其进行更改(即,您永不调用this.setState
)。
If you want to interact with the state in redux, that's where mapStateToProps comes in. Since you've got a mapStateToProps that looks like this: 如果要与Redux中的状态进行交互,则这就是mapStateToProps的来源。由于您有一个如下所示的mapStateToProps:
function mapStateToProps(state) {
const{queue} = state
return {queue}
}
The Channel component will get a prop named queue, and you can interact with it via this. Channel组件将获得一个名为队列的道具 ,您可以通过该队列与之交互。 props .queue.
道具排队。
So, the fix is to update Channel to interact with the prop. 因此,解决方法是更新Channel以与道具进行交互。 Most likely you'll want to delete this.state.queue, as it doesn't seem to serve a purpose and is causing confusion due to its name.
您很可能希望删除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>
}
Additionally, the way you've set up the root reducer has your redux state looking something like this: 此外,设置根缩减器的方式使redux状态看起来像这样:
{
reducer1: {}, // not sure what this contains, since reducer 1 was omitted
reducer2: {
queue: [],
}
}
So if that's really what you want your redux state to look like, your map state to props will need to be updated to this: 因此,如果这确实是您想要的redux状态,那么您需要将props的地图状态更新为:
function mapStateToProps(state) {
const {queue} = state.reducer2;
return {queue};
}
In addition to all the responses about changing this.state.queue
to this.props.queue
, I needed to do a few things. 除了有关将
this.state.queue
更改为this.props.queue
所有响应this.props.queue
,我还需要做一些事情。 Initialize queue in my reducer2
: 在我的
reducer2
初始化队列:
function reducer2(state = {queue:[]}, action) {
switch (action.type) {
case QUEUE_NEW_REQUEST:
return {
...state,
queue: [...state.queue,action.payload],
}
default:
return state
}
}
Change mapStateToProps in Channel.js : 更改mapStateToProps在Channel.js:
function mapStateToProps(state) {
const{queue} = state.reducer2
return {queue}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.