对道具变更做出反应

时间:2018-10-09 12:03:24

标签: reactjs redux rerender

我的问题是,当我在redux存储中更改状态时,基于此状态我会挂载或卸载组件。代码看起来像这样:

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 :(得分:0)

最简单的解决方案是让<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
})

reducers.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
  ...
})

routes.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;

现在,当用户单击<SecondHeadBar/>中的“切换下拉菜单”按钮时,它将更新<DownloadDropdown/>的可见性,而不会影响您的路由树。

答案 1 :(得分:-1)

我认为您可以使用此生命周期方法进行检查。

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

或对于较旧的版本,请检入componentwillreceiveProps并停止重新渲染。