jpthesolver2
jpthesolver2

Reputation: 1155

Redux Store Not Updating Fast Enough

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

Answers (1)

buzatto
buzatto

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

Related Questions