对道具更改做出反应重新渲染
Posted
技术标签:
【中文标题】对道具更改做出反应重新渲染【英文标题】:React rerender on prop change 【发布时间】:2019-03-14 05:00:51 【问题描述】:我的问题是当我在 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
组件中的所有内容都被重新渲染。于是内容一闪而过。
【问题讨论】:
你的问题到底是什么? 如果不清楚,请抱歉。每当道具 dropdownState 发生变化时。并且组件 DownloadDropdown 会在 render() 函数重新渲染的所有内容中安装。所以内容会闪烁,因为它正在从 API 异步加载 @ArnaudChrist 我稍微改变了这个问题。希望这能让它更清楚。 与其卸载并重新安装DownloadDropdown
,不如将dropdownState
作为道具传递给它,然后让它决定何时需要重新渲染/调用服务器。
@JoeClay 我也有这个想法,但我不知道这是否是一个不好的做法,因为这样会一直安装 DownloadDropdown。
【参考方案1】:
最简单的解决方案是让<DownloadDropdown />
成为连接到Redux
的容器组件,并且始终保持挂载状态虽然不可见。然后您可以使用HOC
或始终安装且可见的东西(如<SecondHeadBar />
)并将其连接到切换DownloadDropdown
可见性的Redux action creator
。换句话说,将 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)
下载Dropdown.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/>
的可见性,而不会影响您的路由树。
【讨论】:
【参考方案2】:我认为你可以使用这个生命周期方法来检查。
static getDerivedStateFromProps(nextProps, prevState)
if (nextProps.name !== prevState.name)
return name: nextProps.name;
或者对于旧版本检查componentwillreceiveProps
并停止重新渲染。
【讨论】:
以上是关于对道具更改做出反应重新渲染的主要内容,如果未能解决你的问题,请参考以下文章