Реагировать повторно на изменение реквизита - PullRequest
0 голосов
/ 09 октября 2018

Моя проблема заключается в том, что когда я меняю состояние внутри хранилища с избыточностью и на основании этого состояния я монтирую или размонтирую компонент.Код выглядит следующим образом:

class Main extends Component {

  render() {
    const { dropdownState } = this.props;
    return (
      <div>
        <SecondHeadBar />
        <div className="main">
          <Switch>
            <Route exact path='/' component={withRouter(WebsiteIndex)}/>
            <Route path='/track/:trackid' component={withRouter(MssTrack)}/>
            <Route path='/album/:albumid' component={withRouter(Container.AlbumContainer)}/>
            <Route path='/profile/:userName' component={withRouter(MssUser)}/>
            <Route path='/upload/:albumid' component={withRouter(MssUploadTemplate)}/>
            <Route path='/upload' component={withRouter(MssUploadTemplate)}/>
            <Route path='/admin' component={withRouter(ControlCenter)}/>
            <Route path='/kategorie' component={withRouter(Category)} exact/>
            <Route path='/kategorie/:catName' component={withRouter(Folder)}/>
            <Route path='/notFound' component={withRouter(NotFound)}/>
            <Route path='/meine-eintraege' component={withRouter(Container.MyEntriesContainer)}/>
          </Switch>
        </div>
        {dropdownState ? <DownloadDropdown /> : ''}
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    dropdownState: state.collection.dropdownState
  };
}

function mapDispatchToProps(dispatch) {
  return {
    dispatch
  };
}


export default connect(mapStateToProps, mapDispatchToProps)(Main);

Всякий раз, когда изменяется dropdownState.И компонент DownloadDropdown монтируется, а затем все компоненты Main перерисовываются.Таким образом, содержимое мигает.

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Самым простым решением было бы иметь <DownloadDropdown /> компонент контейнера, который подключен к Redux и всегда будет оставаться подключенным , хотя не виден .Затем вы можете использовать HOC или что-то, что всегда монтируется и отображается (например, <SecondHeadBar />), и подключить его к Redux action creator, который переключает DownloadDropdown видимость.Другими словами, изолируйте Redux на два компонента, а не на все дерево маршрутов.

Рабочий пример: https://codesandbox.io/s/yw4m7yz8r1 (перейдите по маршрутам и нажмите ссылку «Загрузить расписание» вверху!)

Я не уверен, как вы запускаете монтирование / размонтирование, но давайте останемся, что его переключают с помощью кнопки:

SecondHeadBar.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { handleDropdown } from '../actions';

class SecondHeadBar extends Component {
  state = {...}

  componentDidMount = () => { ... }

  render = () => (
    <div>
      ...
      <button onClick={this.props.handleDropdown}>Toggle Dropdown</button>
      ...
    </div>
  )
}

export default connect(null, { handleDropdown })(SecondHeadBar)

DownloadDropdown.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

class DownloadDropdown extends Component {
  state = { ... }

  componentDidMount = () => { ... }


  render = () => (
    this.props.isVisible
      ? <div>I'm visible!</div>
      : null
  )
}

export default connect(state => ({ isVisible: state.dropdown }))(DownloadDropdown)

actions.js

import { TOGGLE_DROPDOWN } from '../types'


export const handleDropdown = () => ({
  type: TOGGLE_DROPDOWN
})

redurs.js

import { TOGGLE_DOWN } from '../types';

...

const dropdownReducer = (state=false, { type, payload }) => {
  switch(type) {
    case TOGGLE_DROPDOWN: return !state
    default: return state
  }
}

export default = combineReducer({
  ...
  dropdown: dropdownReducer
  ...
})

rout.js

const Main = () => (
  <div>
    <SecondHeadBar />
    <div className="main">
      <Switch>
        <Route exact path='/' component={withRouter(WebsiteIndex)}/>
        <Route path='/track/:trackid' component={withRouter(MssTrack)}/>
        <Route path='/album/:albumid' component={withRouter(Container.AlbumContainer)}/>
        <Route path='/profile/:userName' component={withRouter(MssUser)}/>
        <Route path='/upload/:albumid' component={withRouter(MssUploadTemplate)}/>
        <Route path='/upload' component={withRouter(MssUploadTemplate)}/>
        <Route path='/admin' component={withRouter(ControlCenter)}/>
        <Route path='/kategorie' component={withRouter(Category)} exact/>
        <Route path='/kategorie/:catName' component={withRouter(Folder)}/>
        <Route path='/notFound' component={withRouter(NotFound)}/>
        <Route path='/meine-eintraege' component={withRouter(Container.MyEntriesContainer)}/>
      </Switch>
    </div>
    <DownloadDropdown/>
  </div>
);

export default Main;

Теперь, когда пользователь нажимает кнопку «Toggle Dropdown» в <SecondHeadBar/>, он обновляет <DownloadDropdown/> видимость без ущерба для вашего дерева маршрутов.

0 голосов
/ 09 октября 2018

Я думаю, что вы можете использовать этот метод жизненного цикла для проверки.

 static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProps.name !== prevState.name) {
            return { name: nextProps.name};
        }
    }

или для проверки более старой версии в componentwillreceiveProps и остановки повторного рендеринга.

...