Компонент не перерисовывается после изменения состояния в редукторе - PullRequest
0 голосов
/ 26 мая 2019

Допустим, у меня есть ссылка, которая при нажатии добавляет случайное число к массиву в моем объекте состояния с именем queue. Весь массив state.queue отображается на моей странице и обновляется при нажатии на ссылку. В настоящее время у меня есть ссылка, которая должна делать что-то похожее, но после того, как мой редуктор изменяет состояние (добавляет новый элемент в массив), моя страница не (повторно?) Отображает мой компонент, и поэтому страница не обновляется ,

Что я должен сделать, чтобы отобразить полное состояние state.queue на моей странице, включая динамическое обновление при нажатии на ссылку? Вот что у меня есть:

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

Ответы [ 3 ]

2 голосов
/ 26 мая 2019

Как только вы подключите объект state к props с помощью connect, вы получите возвращенные объекты в props.Смотрите это: https://react -redux.js.org / using-реагировать-редукс / connect-mapstate # return .

Итак, вам просто нужно изменить this.state.queue на this.props.queue в вашем Channel.js файле.

И ваш компонент не рендерит, потому что он не зависит от измененного props.Таким образом, внесение предложенных изменений должно решить проблему.

1 голос
/ 26 мая 2019

this.state.queue относится к состоянию, локальному для вашего Channel компонента.Это не избыточное состояние.Вы инициализируете 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>
  }

Кроме того, способ, которым вы установилиВ корне редуктора ваше состояние приращения выглядит примерно так:

{
  reducer1: {}, // not sure what this contains, since reducer 1 was omitted
  reducer2: {
    queue: [],
  }
}

Так что если вы действительно хотите, чтобы ваше состояние приращения выглядело так, ваше состояние карты для реквизита должно быть обновлено следующим образом:

function mapStateToProps(state) {
    const {queue} = state.reducer2;
    return {queue};
}
0 голосов
/ 26 мая 2019

В дополнение ко всем ответам об изменении 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
    }
}

Изменить mapStateToProps в Channel.js :

function mapStateToProps(state) {
    const{queue} = state.reducer2
    return {queue}
}
...