在按钮上单击它会调度功能getCars()
,
这依次发送pendingAction
,然后获取信息,然后发送successAction
或errorAction
。 (我将在下面显示所有代码)。
在加载新信息时,即使它们具有相同的src
,也会将状态更改为待定,然后重新渲染。我希望避免重新渲染,因为这样会使图片闪烁白色。
我的应用程序设置如下:
//index.js
import App from './App';
import * as serviceWorker from './serviceWorker';
import { applyMiddleware, createStore, compose } from 'redux';
import { Provider } from 'react-redux';
import Reducers from './/Reducers';
import thunk from 'redux-thunk';
const middlewares = [thunk];
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(Reducers, composeEnhancers(
applyMiddleware(...middlewares)
));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: somelink
serviceWorker.unregister();
然后我的app.js
//App.js
import React from 'react';
import 'rsuite/dist/styles/rsuite-default.css';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, login, logout } from './/Actions/TestingActions';
import GetCars from './/API/Cars/GetCars';
import { Button } from 'rsuite';
import CarView from './Components/CarTestView/CarView'
//import './index.css';
function App() {
const counter = useSelector(state => state.count)
const logged = useSelector(state => state.loggedin)
const dispatch = useDispatch()
return (
<div className="App">
//
// I hidden some unrelated code here ...
//
<Button onClick={() => dispatch(GetCars())}>Getcars</Button>
<CarView />
</div>
);
}
export default App;
GetCars ...
//GetCars.js
import { apiCarsError, apiCarsSuccess, apiCarsPending } from '../../Actions/TestingActions';
export function GetCars() {
return dispatch => {
dispatch(apiCarsPending());
fetch('https://localhost:44342/API/GetRandomCar')
.then(res => {
res.json().then(res => {
if (res.error) {
throw (res.error);
}
dispatch(apiCarsSuccess(res));
return res;
})
.catch(error => {
dispatch(apiCarsError(error));
})
});
}
}
export default GetCars;
最后是CarView。
import React from 'react';
import { connect, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
import { GetCars } from '../../API//Cars//GetCars';
import { getCars, getCarsPending, getCarsError } from '../../Reducers//TestingReducer';
import { Loader, Placeholder, Panel, /*PanelGroup*/ } from 'rsuite';
//import { CSSTransition, TransitionGroup } from 'react-transition-group';
const { Paragraph } = Placeholder;
function CarView() {
const pending = useSelector(state => state.API.pending)
//const error = useSelector(state => state.API.error)
const cars = useSelector(state => state.API.cars)
if (pending && cars.length === 0) return (
<div>
{console.log("Update is nulio")}
<Loader backdrop content="loading..." vertical />
<Paragraph rows={8}></Paragraph>
</div>
)
if (pending) return (
<div>
{console.log("Update pending")}
<Loader center content="keiciam metus" />
<div>
<Carvaizdas cars={cars} updatePicture={false} />
</div>
</div>
)
if (cars.length === 0) return (<div>{console.log("tuscia")}</div>)
return (
<div>
{console.log("uzkrauta || new info")}
<div>
<Carvaizdas cars={cars} updatePicture={true} />
</div>
</div>
)
}
class Carvaizdas extends React.PureComponent {
shouldComponentUpdate() {
console.log("Should render ?");
console.log(this.props.updatePicture);
return this.props.updatePicture;
}
render() {
console.log("render cars");
return (
<>
<h1>Masinos</h1>
{this.props.cars.map(car => <CarKorta car={car}/>)}
</>
);
}
}
class CarKorta extends React.PureComponent {
render() {
return (
<Panel shaded bordered bodyFill style={{ display: 'inline-block', width: 240, margin: 10 }}>
<div style={{ height: 150, width: 240, display: 'flex', alignItems: 'center', justifyContent: 'center', paddingTop: 10 }}>
<div style={{ height: 'auto', width: 220 }}>
<img src={this.props.car.picture} /*height="240"*/ style={{ maxHeight: 150, height: 'auto', width: 220, borderRadius: 5, boxShadow: "1px 1px 2px #666" }} />
</div>
</div>
<Panel header={this.props.car.make}>
<p>
Year: {this.props.car.year}
<br />
Model: {this.props.car.model}
</p>
</Panel>
</Panel>
);
}
}
const mapStateToProps = state => ({
error: getCarsError(state),
cars: getCars(state),
pending: getCarsPending(state)
})
const mapDispatchToProps = dispatch => bindActionCreators({
CarView: GetCars()
}, dispatch)
export default connect(
mapStateToProps,
mapDispatchToProps
)(CarView);
感谢您的帮助。
答案 0 :(得分:1)
问题在于在不同条件下使用组件Carvaizdas
的2个实例。这样就没有shouldComponentUpdate
钩子的意义,后者是特定于PER INSTANCE的。
if (pending)
return (
<div>
{console.log("Update pending")}
<Loader center content="keiciam metus" />
<div>
<Carvaizdas cars={cars} updatePicture={false} /> {/** first component instance */}
</div>
</div>
);
if (cars.length === 0) return <div>{console.log("tuscia")}</div>;
return (
<div>
{console.log("uzkrauta || new info")}
<div>
<Carvaizdas cars={cars} updatePicture={true} /> {/** second component instance */}
</div>
</div>
);
要使shouldComponentUpdate
正常工作,应该只有一个实例
return (
<div>
{console.log("uzkrauta || new info")}
<div>
<Carvaizdas cars={cars} />
</div>
</div>
);
在此组件中,使用shouldComponentUpdate
也没有意义
class Carvaizdas extends React.PureComponent {
render() {
console.log("render cars");
return (
<>
<h1>Masinos</h1>
{this.props.cars.map(car => <CarKorta car={car}/>)}
</>
);
}
}
这仅对CarKorta
有意义。您应该从shouldComponentUpdate
中删除Carvaizdas
并将其添加到CarKorta
中。另外,您必须以CarKorta
状态存储上一张图片,以便能够与下一张图片进行比较。为此,您必须使用getDerivedStateFromProps
class CarKorta extends React.PureComponent {
state = {
car: null,
};
shouldComponentUpdate(nextProps) {
return !this.state.car || this.state.car.picture !== nextProps.car.picture;
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
car: { ...nextProps.car },
};
}
render() {
return (
<Panel
shaded
bordered
bodyFill
style={{ display: "inline-block", width: 240, margin: 10 }}
>
<img
src={this.state.car.picture}
/*height="240"*/ style={{
maxHeight: 150,
height: "auto",
width: 220,
borderRadius: 5,
boxShadow: "1px 1px 2px #666",
}}
/>
</Panel>
);
}
}
答案 1 :(得分:0)
我这样更改CarView,现在可以使用了。
import React from 'react';
import { connect, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
import { GetCars } from '../../API//Cars//GetCars';
import { getCars, getCarsPending, getCarsError } from '../../Reducers//TestingReducer';
import { Loader, Placeholder, Panel, /*PanelGroup*/ } from 'rsuite';
//import { CSSTransition, TransitionGroup } from 'react-transition-group';
const { Paragraph } = Placeholder;
function CarView() {
const pending = useSelector(state => state.API.pending)
//const error = useSelector(state => state.API.error)
const cars = useSelector(state => state.API.cars)
if (pending && cars.length === 0) return (
<div>
{console.log("Update is nulio")}
<Loader backdrop content="loading..." vertical />
<Paragraph rows={8}></Paragraph>
</div>
)
if (cars.length === 0) return (<div>{console.log("tuscia")}</div>)
return (
<div>
{console.log("uzkrauta || new info")}
{pending ? <Loader center content="keiciam metus" />: <></>}
<div>
<Carvaizdas cars={cars} />
</div>
</div>
)
}
class Carvaizdas extends React.PureComponent {
render() {
console.log("render cars");
return (
<>
<h1>Masinos</h1>
{this.props.cars.map(car => <CarKorta car={car}/>)}
</>
);
}
}
class CarKorta extends React.PureComponent {
render() {
return (
<Panel shaded bordered bodyFill style={{ display: 'inline-block', width: 240, margin: 10 }}>
<div style={{ height: 150, width: 240, display: 'flex', alignItems: 'center', justifyContent: 'center', paddingTop: 10 }}>
<div style={{ height: 'auto', width: 220 }}>
<img src={this.props.car.picture} /*height="240"*/ style={{ maxHeight: 150, height: 'auto', width: 220, borderRadius: 5, boxShadow: "1px 1px 2px #666" }} />
</div>
</div>
<Panel header={this.props.car.make}>
<p>
Year: {this.props.car.year}
<br />
Model: {this.props.car.model}
</p>
</Panel>
</Panel>
);
}
}
const mapStateToProps = state => ({
error: getCarsError(state),
cars: getCars(state),
pending: getCarsPending(state)
})
const mapDispatchToProps = dispatch => bindActionCreators({
CarView: GetCars()
}, dispatch)
export default connect(
mapStateToProps,
mapDispatchToProps
)(CarView);