Home > Software design >  How to use local scope inside useEffect hook?
How to use local scope inside useEffect hook?

Time:01-14

The following code works fine:

useEffect(() => {
  const apiService = new APIClient('api address');
  var topicCommentsReq = new GetTopicDetailsRequest();
  topicCommentsReq.setTopicCid(Buffer.from("123", "hex"));
  apiService.getTopicDetails(topicCommentsReq, {}, function (err, response) {
    console.log(`response : ${JSON.stringify(response)}`);
  });
}

I want to convert this callback style function to async/await style, so i did something like this:

const promisifyFn =
  (fn: Function) =>
  (...args: any[]) =>
    new Promise((resolve, reject) => {
      return fn(...args, (err: Error, data: any) => {
        return err ? reject(err) : resolve(data);
      });
    });

useEffect(() => {
  (async () => {
    const apiService = new APIClient("api address");
    const topicCommentsReq = new GetTopicDetailsRequest();
    topicCommentsReq.setTopicCid(Buffer.from("123", "hex"));
    const getTopicDetails = promisifyFn(apiService.getTopicDetails);
    try {
      const res = await getTopicDetails(topicCommentsReq, {});
      console.log(`response : ${JSON.stringify(res)}`);
    } catch (e) {
      console.log(e);
    }
  })();
});

The following error message shows up:

TypeError: Cannot read properties of undefined (reading 'client_')
 if (callback !== undefined) {
      return this.client_.rpcCall(
        this.hostname_  
          '/StelaPlatform.GRPC.API/GetTopicDetails',
        request,
        metadata || {},
        this.methodDescriptorGetTopicDetails,
        callback);
    }

My guess is this problem related with the lcoal scope. When the function run inside async function, the this scope is different. But how should I resolve this issue in general?

CodePudding user response:

The problem is in passing the function reference to apiService.getTopicDetails, it loses its this context.

In order to keep the prototype function in its prototype, you should use either an arrow function...

const getTopicDetails = promisifyFn((...args) =>
  apiService.getTopicDetails(...args));

or Function.prototype.bind()

const getTopicDetails = promisifyFn(apiService.getTopicDetails.bind(apiService));
  • Related