无法让 Redux mapStateToProps 在四分之一的组件上工作
Can't get Redux mapStateToProps work on one out of four Components
我使用 React Redux Saga 并有 3 个组件接收 mapStateToProps
ok 当 Sage 发送到我的 reducer
时。第四个 Component
不会触发 render()
即使我在组件的 render()
中放置了一个断点 console.log:
const mapStateToProps = state => {
return { articles: state.rootReducer.remoteArticles };
};
并且可以看到上面的Store
remoteArticles
有数据
我制作了一部 40 秒的电影来展示发生的事情,
- 开始调试
- mapStateToProps 因空文章而中断
- Saga 调度时reducer 中断
- mapStateToProps 再次与保存数据的文章中断
- 接下来
render()
应该被调用但不是..
https://drive.google.com/file/d/1_QuKQd0YGbMuxrQ-qeQbF5mwlWLk0lly/view
Component
的完整代码 SliderWrapper.js 不会触发 render()
/* eslint-disable react/destructuring-assignment */
/* eslint-disable react/jsx-props-no-spreading */
import Slider from 'react-slick';
import { connect } from 'react-redux';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import React from 'react';
// import Resume from '../../resume.json';
import albums from '../../albumData.json';
const la = require('lodash');
class SliderWrapper extends React.Component {
shouldComponentUpdate(nextProps) {
// certain condition here, perhaps comparison between this.props and nextProps
// and if you want to update slider on setState in parent of this, return true, otherwise return false
const { updateCount } = nextProps;
const { updateCounter } = this.props;
if (updateCounter !== updateCount) {
return false;
}
// console.log("shouldComponentUpdate");
return true;
}
sliders() {
const { articles } = this.props;
if (articles.length === 0) return null;
return articles.weeks.map(week => {
let photo = la.find(albums, { weekNumber: week.weekNumber });
photo = encodeURIComponent(`${process.env.PUBLIC_URL}/images/weeks/${week.weekNumber}/${photo.coverImage}`);
const { onImageClick } = this.props;
return (
// Timeline items
<section className="timeline-carousel" key={week.weekNumber}>
<h1>week {week.weekNumber}</h1>
<div className="timeline-carousel__item-wrapper" data-js="timeline-carousel">
<div className="timeline-carousel__item">
<div className="timeline-carousel__image">
<img onClick={() => onImageClick(week.weekNumber)} alt="CoverImage" src={photo} />
<h2>UNDER CONSTRUCTION IN PROGRES..</h2>
</div>
<div className="timeline-carousel__item-inner">
<div className="pointer" />
<span className="year">{week.year}</span>
<span className="month">{week.albumDate}</span>
<p>{week.summary}</p>
<a href="#/" className="read-more">
Read more, Dev should go to read more
</a>
</div>
</div>
</div>
</section>
);
});
}
render() {
const { afterChanged } = this.props;
const { beforeChanged } = this.props;
const settings = {
dots: false,
arrows: false,
autoplay: false,
infinite: true,
lazyLoad: false,
swipeToSlide: true,
centerMode: false,
focusOnSelect: false,
className: 'center',
slidesToShow: 4,
afterChange: afterChanged,
beforeChange: beforeChanged,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: false,
},
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
initialSlide: 2,
},
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
},
},
],
};
return (
<div>
<Slider
ref={slider => {
this.slider = slider;
}}
{...settings}
>
{this.sliders()}
</Slider>
</div>
);
}
}
const mapStateToProps = state => {
return { articles: state.rootReducer.remoteArticles };
};
const Aaa = connect(mapStateToProps, null)(SliderWrapper);
export default Aaa;
使用 `SliderWrapper
Component
Timeline.js 的完整代码
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import React from 'react';
import SliderWrapper from './SliderWrapper';
class Timeline extends React.Component {
constructor(props) {
super(props);
this.changeHandler = this.changeHandler.bind(this);
this.changeSlider = this.changeSlider.bind(this);
this.state = {
slideIndex: 1,
updateCount: 0,
};
}
onImageClick = val => {
const { onChangeAlbum } = this.props;
onChangeAlbum(val);
};
onChangeUpdateCount() {
this.changeUpdateCount.bind(this);
}
changeUpdateCount() {
const { updateCount } = this.state;
this.setState(
{
updateCount: updateCount + 1,
},
// () => console.log(`test state after update: ${updateCount}`),
);
}
changeSlider() {
this.setState({
slideIndex: this.sliderWrapper.slider.innerSlider.state.currentSlide,
});
// const { onChangeAlbum } = this.props;
// onChangeAlbum(this.sliderWrapper.slider.innerSlider.state.currentSlide);
}
changeHandler(e) {
this.sliderWrapper.slider.slickGoTo(e.target.value);
}
render() {
const { slideIndex } = this.state;
const { updateCount } = this.state;
return (
<section className="hero is-dark has-bg-image">
<div className="c" id="timeline">
<p>Your at Album: {slideIndex} </p>
<input onChange={this.changeHandler} value={slideIndex} type="range" min={0} max={50} />
<SliderWrapper
onImageClick={this.onImageClick}
ref={sliderWrapper => {
this.sliderWrapper = sliderWrapper;
}}
beforeChanged={this.changeUpdateCount.bind(this)}
afterChanged={this.changeSlider.bind(this)}
slideIndex={slideIndex}
updateCounter={updateCount}
/>
</div>
</section>
);
}
}
export default Timeline;
您已经实现了 shouldComponentUpdate。通过这样做 - 您的组件不会 re-render,仅当某些条件发生变化时。尝试删除此功能,看看是否适合您。
我使用 React Redux Saga 并有 3 个组件接收 mapStateToProps
ok 当 Sage 发送到我的 reducer
时。第四个 Component
不会触发 render()
即使我在组件的 render()
中放置了一个断点 console.log:
const mapStateToProps = state => {
return { articles: state.rootReducer.remoteArticles };
};
并且可以看到上面的Store
remoteArticles
有数据
我制作了一部 40 秒的电影来展示发生的事情,
- 开始调试
- mapStateToProps 因空文章而中断
- Saga 调度时reducer 中断
- mapStateToProps 再次与保存数据的文章中断
- 接下来
render()
应该被调用但不是..
https://drive.google.com/file/d/1_QuKQd0YGbMuxrQ-qeQbF5mwlWLk0lly/view
Component
的完整代码 SliderWrapper.js 不会触发 render()
/* eslint-disable react/destructuring-assignment */
/* eslint-disable react/jsx-props-no-spreading */
import Slider from 'react-slick';
import { connect } from 'react-redux';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import React from 'react';
// import Resume from '../../resume.json';
import albums from '../../albumData.json';
const la = require('lodash');
class SliderWrapper extends React.Component {
shouldComponentUpdate(nextProps) {
// certain condition here, perhaps comparison between this.props and nextProps
// and if you want to update slider on setState in parent of this, return true, otherwise return false
const { updateCount } = nextProps;
const { updateCounter } = this.props;
if (updateCounter !== updateCount) {
return false;
}
// console.log("shouldComponentUpdate");
return true;
}
sliders() {
const { articles } = this.props;
if (articles.length === 0) return null;
return articles.weeks.map(week => {
let photo = la.find(albums, { weekNumber: week.weekNumber });
photo = encodeURIComponent(`${process.env.PUBLIC_URL}/images/weeks/${week.weekNumber}/${photo.coverImage}`);
const { onImageClick } = this.props;
return (
// Timeline items
<section className="timeline-carousel" key={week.weekNumber}>
<h1>week {week.weekNumber}</h1>
<div className="timeline-carousel__item-wrapper" data-js="timeline-carousel">
<div className="timeline-carousel__item">
<div className="timeline-carousel__image">
<img onClick={() => onImageClick(week.weekNumber)} alt="CoverImage" src={photo} />
<h2>UNDER CONSTRUCTION IN PROGRES..</h2>
</div>
<div className="timeline-carousel__item-inner">
<div className="pointer" />
<span className="year">{week.year}</span>
<span className="month">{week.albumDate}</span>
<p>{week.summary}</p>
<a href="#/" className="read-more">
Read more, Dev should go to read more
</a>
</div>
</div>
</div>
</section>
);
});
}
render() {
const { afterChanged } = this.props;
const { beforeChanged } = this.props;
const settings = {
dots: false,
arrows: false,
autoplay: false,
infinite: true,
lazyLoad: false,
swipeToSlide: true,
centerMode: false,
focusOnSelect: false,
className: 'center',
slidesToShow: 4,
afterChange: afterChanged,
beforeChange: beforeChanged,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: false,
},
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
initialSlide: 2,
},
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
},
},
],
};
return (
<div>
<Slider
ref={slider => {
this.slider = slider;
}}
{...settings}
>
{this.sliders()}
</Slider>
</div>
);
}
}
const mapStateToProps = state => {
return { articles: state.rootReducer.remoteArticles };
};
const Aaa = connect(mapStateToProps, null)(SliderWrapper);
export default Aaa;
使用 `SliderWrapper
Component
Timeline.js 的完整代码
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import React from 'react';
import SliderWrapper from './SliderWrapper';
class Timeline extends React.Component {
constructor(props) {
super(props);
this.changeHandler = this.changeHandler.bind(this);
this.changeSlider = this.changeSlider.bind(this);
this.state = {
slideIndex: 1,
updateCount: 0,
};
}
onImageClick = val => {
const { onChangeAlbum } = this.props;
onChangeAlbum(val);
};
onChangeUpdateCount() {
this.changeUpdateCount.bind(this);
}
changeUpdateCount() {
const { updateCount } = this.state;
this.setState(
{
updateCount: updateCount + 1,
},
// () => console.log(`test state after update: ${updateCount}`),
);
}
changeSlider() {
this.setState({
slideIndex: this.sliderWrapper.slider.innerSlider.state.currentSlide,
});
// const { onChangeAlbum } = this.props;
// onChangeAlbum(this.sliderWrapper.slider.innerSlider.state.currentSlide);
}
changeHandler(e) {
this.sliderWrapper.slider.slickGoTo(e.target.value);
}
render() {
const { slideIndex } = this.state;
const { updateCount } = this.state;
return (
<section className="hero is-dark has-bg-image">
<div className="c" id="timeline">
<p>Your at Album: {slideIndex} </p>
<input onChange={this.changeHandler} value={slideIndex} type="range" min={0} max={50} />
<SliderWrapper
onImageClick={this.onImageClick}
ref={sliderWrapper => {
this.sliderWrapper = sliderWrapper;
}}
beforeChanged={this.changeUpdateCount.bind(this)}
afterChanged={this.changeSlider.bind(this)}
slideIndex={slideIndex}
updateCounter={updateCount}
/>
</div>
</section>
);
}
}
export default Timeline;
您已经实现了 shouldComponentUpdate。通过这样做 - 您的组件不会 re-render,仅当某些条件发生变化时。尝试删除此功能,看看是否适合您。