Reputation: 1155
I have this incredibly annoying problem where my redux store (seems) to be not updating in time for what I'm guessing is some sort of React pre-emptive optimization. Here is my App component
function mapStateToProps(store: FoAppState): AppState {
return {
isCurrentlySelectingARoad: store.isSelectingRoad,
};
}
function mapDispatchToProps(dispatch: Dispatch) {
return {
activateRoadSelects: (s: boolean) => {
return dispatch(activateRoadSelection(s));
},
};
}
const connector = connect(mapStateToProps, mapDispatchToProps);
type AppProps = ConnectedProps<typeof connector>;
class App extends React.Component<AppProps, {}> {
evaluateEndTurnEligibility() {
const { isCurrentlySelectingARoad } = this.props
// ** PROBLEM **
console.log(isCurrentlySelectingARoad);
if (
!isCurrentlySelectingARoad
) {
this.setState({
...this.state,
canEndTurn: true,
});
}
}
selectRoadSpotCB() {
this.props.activateRoadSelects(false);
const millisecondsToWait = 1000;
setTimeout(() => {
this.evaluateEndTurnEligibility();
}, millisecondsToWait);
}
}
render(){
<Road cb={selectRoadCB} />
}
Road Component
type Props = {
cb: Function;
};
type HPProps = {
tiles: Array<TileModel>;
};
function mapStateToProps(store: FoAppState): HPProps {
return {
tiles: store.boardToBePlayed.listOfTiles,
};
}
const connector = connect(mapStateToProps);
type ReduxProps = ConnectedProps<typeof connector>;
};
type HPProps = {
tiles: Array<TileModel>;
};
function mapStateToProps(store: FoAppState): HPProps {
return {
tiles: store.boardToBePlayed.listOfTiles,
};
}
const connector = connect(mapStateToProps);
type ReduxProps = ConnectedProps<typeof connector>;
type HighlightProps = ReduxProps & Props;
class Road extends Component<HighlightProps, {}> {
constructor(props: HighlightProps) {
super(props);
}
selectedARoadSpot(): void {
socket.emit(
"addRoad",
"1",
);
this.props.finishedSelectingCallback();
}
render() {
return (
<circle
onClick={this.selectedARoadSpot}
/>
);
}
}
export default connector(Road);
Reducer
import { SelectingRoadAction, SELECTING_ROAD } from "../Actions";
export default function isSelectingRoad(
state: boolean = false,
action: SelectingRoadAction
): boolean {
switch (action.type) {
case SELECTING_ROAD:
console.log(action.isSelecting);
return action.isSelecting;
default:
return state;
}
}
The problem is that in that when someone clicks on the 'Road', it eventually reaches the callback and goes to 'evaluteTurnEligibility' and although the console log before the if
says false, the if doesn't actually go through. For some reason, adding the timeout that waits a second in the evaluateElg method actually solves this. Dispatch is synchronous, so is there something that I am just overlooking, or is this a problem with React trying to optimize stuff for me?
Upvotes: 0
Views: 758
Reputation: 10382
I would call this.evaluateEndTurnEligibility()
at componentDidUpdate
life cycle (remember to verify if prevprops are different from next props).
Trying to access props / state at given function that changes in advance state often leads to mess. Even though dispatch is sync, react will then receive new changed props, will rerender, and all that may lead to you have not the next props at time needed.
Upvotes: 1