简体   繁体   English

Reducer中的状态更改后,组件未重新渲染

[英]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 . 使用connectstate对象连接到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.queuethis.props.queueChannel.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.queueChannel组件本地的状态。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM