![](/img/trans.png)
[英]React - prevent re-rendering component if redux state is changed
[英]Prevent component from re-rendering when property not used in render function React Redux
我正在为重新渲染的组件而苦苦挣扎。
我正在使用 Redux 来管理我的状态。 在一个组件中,除了渲染 function 之外,我在我的组件(类)的某些方法中使用了我的 state 中的属性(isPlaying:bool)和 mapStateToProps,并且我使用一些动作创建者来调度isPlaying的更改。 顺便说一句,我正在使用连接(react-redux)在另一个子组件(音乐播放器)中使用isPlaying 。
这就是我所期待的:
当isPlaying更改时,父组件不会重新渲染,音乐栏会重新渲染,我继续在父组件的方法中使用isPlaying 。
有什么问题:
即使我没有在渲染方法中使用isPlaying ,父组件也会重新渲染。
抱歉,如果我在阅读时确实让您感到困惑,我不是以英语为母语的人。
提前致谢。
编辑:添加代码的简化版本。
我最初的 state:
export default {
// Some Irrelevant Properties
...
playlist: {
isPlaying: false,
playingTrack: null,
nextTrack: null,
prevTrack: null,
views: null,
totalListens: null,
tracks: []
}
};
这是我的父组件。 (应用程序.js)
import ...
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
widgets: [],
links: [],
clickedTrack: null
}
this.musicBarRef = React.createRef()
this._isMounted = false;
// Binding this to the methods used in this Component
...
}
// All my methods here
// Example of one function
playTrack() {
let {isPlaying} = this.props
if (isPlaying) {
// Pause
} else {
// Play
}
}
render() {
<>
// Some irrelevant components (don't use isPlaying)
<TracksPlaylist tracks={this.props.tracks} and some the methods created above />
<MusicBar ref={this.musicBarRef} and some methods created above />
// Example of one irrelevant component that re-renders
<Footer />
</>
}
}
const mapStateToProps = (state) => {
return {
isPlaying: state.playlist.isPlaying,
selectedTrack: state.playlist.playingTrack,
nextTrack: state.playlist.nextTrack,
prevTrack: state.playlist.prevTrack,
tracks: state.playlist.tracks,
}
}
const mapDispatchToProps = {
setPlaying: startPlaying, // Set isPlaying: true
setNotPlaying: stopPlaying, // Set isPlaying: false
// Some Irrelevent Action Creators
...
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
这是我的减速机
import * as types from "../actions/actionTypes";
import initialState from "./initialState";
export default function musicPlayerReducer(state = initialState.playlist, action) {
switch (action.type) {
// Some irrelevant cases
...
case types.STOP_PLAYING:
return {...state, isPlaying: false}
case types.START_PLAYING:
return {...state, isPlaying: true}
case types.NEXT_TRACK_FOUND:
return {...state, nextTrack: action.track}
case types.PREV_TRACK_FOUND:
return {...state, prevTrack: action.track}
case types.CURRENT_TRACK_FOUND:
return {...state, playingTrack: action.track}
default:
return state
}
}
App.js 中提到的 TracksPlaylist
import ...
class TracksPlaylist extends React.Component {
constructor(props) {
super(props)
}
render() {
let {tracks, onPlayClick ... and other methods from App.js} = this.props
return (
<div className="songs">
{
Object.values(tracks).length > 0 ?
Object.values(tracks).map((item, index) => {
return <Track onPlayClick={onPlayClick} key={index} item={item} />
}) :
''
}
</div>
)
}
}
const mapStateToProps = (state) => {
return {
tracks: state.playlist.tracks,
}
}
const mapDispatchToProps = {
setPlaying: startPlaying,
setNotPlaying: stopPlaying,
// Some irrelevant functions
...
}
export default connect(mapStateToProps, mapDispatchToProps)(Tracks)
轨道组件
import ...
class Track extends React.Component {
constructor(props) {
super(props)
}
hasInteraction(interactionType, trackId) {
return false
}
render() {
let {onPlayClick, item} = this.props
return (
<div key={item.track_id} className="track" id={item.track_id} data-category={item.category_name}>
// A lot of irrelevant JSX :)
<TrackAction onPlayClick={onPlayClick} item={item} />
</div>
</div>
)
}
}
export default Track
这是 TrackAction(它使用 isPlaying):
import ...
function TrackAction({item, isPlaying, playingTrack, onPlayClick}) {
return (
<div className="status action play-track" onClick={onPlayClick}>
<i id={item.track_id} className={isPlaying && playingTrack.track_id === item.track_id ? 'fas fa-pause' : 'fas fa-play'} />
</div>
)
}
const mapStateToProps = (state) => {
return {
isPlaying: state.playlist.isPlaying,
playingTrack: state.playlist.playingTrack
}
}
export default connect(mapStateToProps)(TrackAction)
我确实使用了 TrackAction 来重新渲染这个组件,因为 isPlaying 发生了变化,并且它被注册到这个组件并在它的 render() 中使用。
再次感谢。
尽管您没有在render
方法中使用isPlaying
,但由于mapStateToProps
绑定,您仍在订阅更改。
每当State || Props
State || Props
更改,React 只会重新渲染新更新的state || props
只是浅比较的state || props
。
这就是为什么你的父母被重新渲染的原因。
一种可能的解决方案是覆盖shouldcomponentupdate
https://reactjs.org/docs/react-component.html#shouldcomponentupdate
使用 shouldComponentUpdate() 让 React 知道组件的 output 是否不受 state 或 props 的当前更改的影响。 默认行为是在每个 state 更改时重新渲染。
默认为真。 如果覆盖并返回 false,则不会调用 UNSAFE_componentWillUpdate()、render() 和 componentDidUpdate()。
示例代码:
shouldComponentUpdate(nextProps, nextState) {
return <enter_your_condition_to_be_true>; // else false
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.