0

I'm not able to read current state inside refreshWarehouseCallback function. Why? My component:

export function Schedules({ tsmService, push, pubsub }: Props) {
    const [myState, setMyState] = useState<any>(initialState);

 useEffect(() => {
        service
            .getWarehouses()
            .then((warehouses) =>
                getCurrentWarehouseData(warehouses) // inside of this function I can without problems set myState
            )
            .catch(() => catchError());

        const pushToken = push.subscribe('public/ttt/#');
        const pubSubToken = pubsub.subscribe(
            'push:ttt.*',
            refreshWarehouseCallback // HERE IS PROBLEM, when I try to read current state from this function I get old data, state changed in other functions cannot be read in thi function
        );

        return () => {
            pubsub.unsubscribe(pubSubToken);
            push.unsubscribe(pushToken);
        };
    }, []);

...

function refreshWarehouseCallback(eventName: string, content: any) {
      const {warehouseId} = myState; // undefined!!!
      case pushEvents.ramp.updated: {
}
}


return (
        <Views
            warehouses={myState.warehouses}
            allRamps={myState.allRamps}
            currentWarehouse={myState.currentWarehouse}
            pending={myState.pending}
            error={myState.error}
        />

I have to use useRef to store current state additionally to be able to rerender the whole component.

My question is - is there any other solution without useRef? Where is the problem? Calback function doesn't work with useState hook?

1 Answer 1

1

Your pub/sub pattern does not inherit React's states. Whenever subscribe is triggered, and your callback function is initialized, that callback will not get any new values from myState.

To be able to use React's states, you can wrap refreshWarehouseCallback into another function like below

//`my state` is passed into the first function (the function wrapper)
//the inner function is your original function
const refreshWarehouseCallback =
  (myState) => (eventName: string, content: any) => {
    const { warehouseId } = myState;
    //your other logic
  };

And then you can add another useEffect to update subscribe after state changes (in this case, myState updates)

 //a new state to store the updated pub/sub after every clean-up
const [pubSubToken, setPubSubToken] = useState();

useEffect(() => {
  //clean up when your state updates
  if (pubSubToken) {
    pubsub.unsubscribe(pubSubToken);
  }
  const updatedPubSubToken = pubsub.subscribe(
    "push:ttt.*",
    refreshWarehouseCallback(myState) //execute the function wrapper to pass `myState` down to your original callback function
  );

  //update new pub/sub token
  setPubSubToken(updatedPubSubToken);

  return () => {
    pubsub.unsubscribe(updatedPubSubToken);
  };

//add `myState` as a dependency
}, [myState]);

//you can combine this with your previous useEffect
useEffect(() => {
  const pushToken = push.subscribe("public/ttt/#");

  return () => {
    pubsub.unsubscribe(pushToken);
  };
}, []);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.