DEV Community

bravemaster619
bravemaster619

Posted on • Edited on • Originally published at stackoverflow.com

Event-driven approach in React hooks?

I'd like to "fire an event" in one component, and let other components "subscribe" to that event and do some work in React.

For example, here is a typical React project.

I have a model, fetch data from server and several components are rendered with that data.

interface Model {
   id: number;
   value: number;
}

const [data, setData] = useState<Model[]>([]);
useEffect(() => {
   fetchDataFromServer().then((resp) => setData(resp.data));
}, []);

<Root>
   <TopTab>
     <Text>Model with large value count:  {data.filter(m => m.value > 5).length}</Text>
   </TobTab>
   <Content>
      <View>
         {data.map(itemData: model, index: number) => (
            <Item key={itemData.id} itemData={itemData} />
         )}
      </View>
   </Content>
   <BottomTab data={data} />
</Root>
Enter fullscreen mode Exit fullscreen mode

In one child component, a model can be edited and saved.

const [editItem, setEditItem] = useState<Model|null>(null);
<Root>
   <TopTab>
     <Text>Model with large value count:  {data.filter(m => m.value > 5).length}</Text>
   </TobTab>
   <ListScreen>
      {data.map(itemData: model, index: number) => (
          <Item 
             key={itemData.id} 
             itemData={itemData} 
             onClick={() => setEditItem(itemData)}
          />
      )}
   </ListScreen>
   {!!editItem && (
       <EditScreen itemData={editItem} />
   )}
   <BottomTab data={data} />
</Root>
Enter fullscreen mode Exit fullscreen mode

Let's assume it's EditScreen:

const [model, setModel] = useState(props.itemData);

<Input 
   value={model.value}
   onChange={(value) => setModel({...model, Number(value)})}
/>
<Button 
   onClick={() => {
       callSaveApi(model).then((resp) => {
           setModel(resp.data);
           // let other components know that this model is updated
       })
   }}
/>
Enter fullscreen mode Exit fullscreen mode

How can I let TopTab, BottomTab and ListScreen component to update data

  • without calling API from server again and
  • not passing updateData function as props

I'd like to fire an event (e.g. "model-update") with an argument (changed model) and let other components subscribe to that event and change their data.

Is it possible using React hooks?

How to implement event-driven approach in React hooks?

Please let me know your opinions. Leave comments here or help me in Stack Overflow!

23

I'd like to "fire an event" in one component, and let other components "subscribe" to that event and do some work in React.

For example, here is a typical React project.

I have a model, fetch data from server and several components are rendered with that data.

interface Model {

Top comments (1)

Collapse
 
dceddia profile image
Dave Ceddia • Edited

You ruled out passing an updateData function down, but that is the "plain React way" to do this: pass a callback down, and children can call it when there's new data. Hooks don't change that model.

There are libraries that implement the observer pattern, like MobX, that can detect changes and re-render components that use the changed data.

There's also react-query, which is pretty much built to solve your fetching/updating/reloading data use case. It maintains a global cache of responses, and every query & mutation feeds into that same cache, so changes will cause the components using the data to re-render.