5

I have a context that using a class instance as context value. After I updated the class instance. The change doesn't reflect in the consumer. Consumer still get the old class value. Can someone point me the direction of how to achieve this?

// Service class
class Service {
   name = "oldName"
   function changeName(newName){
       this.name = newName;
   }
}

//Context provider
function App() {
  const service = new Service();
  return (
    <ServiceContext.Provider value={service}>
      <Home />
    </ServiceContext.Provider>
  );
}

Then I try to change the name attribute of this service in one component.

import React, { useContext } from "react";

const SomeComponent = () => {
  const service = useContext(ServiceContext);
  const onClick = () => {
    service.changeName('newName')
    console.log(service.name) //here the name has updated
  }
  return <button onClick={onClick}>Change</h1>;
};

And try to get the updated value from the component.

//Context consumer
import React, { useContext } from "react";

const MyComponent = () => {
  const service = useContext(ServiceContext);

  return <h1>{service.name}</h1>;
};

but in another consumer. service.name didn't get update. May I know why is that?

Youwei Zhu
  • 79
  • 1
  • 8

1 Answers1

3

That's not how React works, it is not a "real reactive", just because you changed a value it doesn't mean the component will re-render.

The only way to cause a re-render is to use React's API.

See Rendering a Component in docs.

class Service {
  name = "oldName";
  changeName(newName) {
    this.name = newName;
  }
}

const service = new Service();

// Provider
function App() {
  const [, render] = useReducer(p => !p, false);
  return (
    <ServiceContext.Provider value={{ service, render }}>
      <SomeComponent />
    </ServiceContext.Provider>
  );
}

// Usage
const SomeComponent = () => {
  const { service, render } = useContext(ServiceContext);
  const onClick = () => {
    service.changeName("newName");
    render();
  };
  return <button onClick={onClick}>{service.name}</button>;
};

Edit charming-bardeen-bdg01

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • 1
    this looks good. thanks. 1) I forget to initiate the Service outside the component. 2) need something to trigger re-render – Youwei Zhu Jun 08 '20 at 13:13