3

I use pusher-js to receive data from the backend.


I configure it in useEffect like this:

  useEffect(() => {
    const pusher = new Pusher('my_app_id', {
      cluster: 'us3',
    });

    const channel = pusher.subscribe('messages');

    channel.bind('send-message', (data) => {

    });
  }, []);

In the callback of the .bind method, I want to access the react state. The problem is, that if it gets updated, this callback still has the old version.

channel.bind('send-message', (data) => {
    // here is my outdated state
});

How can I acces new, updated state inside this callback? Thanks in advance

Velrin Black
  • 412
  • 1
  • 4
  • 10
  • Try add your react state variable to your dependency list (the array you pass as second paramenter in your useEffect call) – Syder Dec 26 '20 at 08:47

2 Answers2

3

Use another useEffect with the updated state in your dependency array of the useEffect,as soon as the state gets updated that useEffect will. be triggered and inside it you can access the updated state.

Sakshi
  • 1,464
  • 2
  • 8
  • 15
2

I was stuck on the same problem for quite a long time. The way I finally solved this is to store the channel and rebind the event every time the state (which I want to access in the bind callback) changed. Here is a code snippet to help you understand better.

VERY IMPORTANT - Do not forget to unbind the event from the channel before rebinding it. As rebinding without unbinding prior binds would just create additional listeners for the event and all the listeners will fire when the event occurs and it will be a mess. Learnt it the hard way :")

Don't know if this is the best method but worked for me.

const [pusherChannel, setPusherChannel] = useState(null);
const [data, setData] = useState(null);

// TRIGGERED ON MOUNT
useEffect(() => {
  const pusher = new Pusher(APP_KEY, {
    cluster: APP_CLUSTER
  });
  const channel = pusher.subscribe(CHANNEL_NAME);
  setPusherChannel(channel);
  // PREVIOUSLY
  // channel.bind(EVENT_NAME, (pusherData) => {
  //   ...
  //   Accessing "data" here would give the state used
  //   during binding the event
  //});
}, []);

// TRIGGERED ON CHANGE IN "data"
useEffect(() => {
  console.log("Updated data : ", data);
  if(pusherChannel && pusherChannel.bind){
    console.log("Unbinding Event");
    pusherChannel.unbind(EVENT_NAME);
    console.log("Rebinding Event");
    pusherChannel.bind(EVENT_NAME, (pusherData) => {
      // USE UPDATED "data" here
    }
  }
}, [pusherChannel, data]);

Reference -

Sayan Das
  • 51
  • 5