softechie
softechie

Reputation: 133

How to call Parent containers function from child component in Reactjs

My application renders dynamic tiles by user and the tiles need to be re-arranged based on external configuration, StyleWrapper need to be a common container component that can be used in other projects too. Following is our UI component structure:

<StyleWrapper>
 <Header />
 <Content>
  <PortletTiles />
 </Content>
</StyleWrapper>

Given above structure, I have a function in StyleWrapper.tsx called arrangeTiles() which arranges tiles based on external configuration.

My question is how to call arrangeTiles() function from child component PortletTiles.tsx

StyleWrapper.tsx --> Parent Wrapper Container component

function StyleWrapper(props:any) {
  let arrangeTiles= () => {  
    // Arrange Tile logic
  };
  return (
    <div id="cnplStyleWrapper">
        {props.children}
    </div>
  );
}

export default StyleWrapper;

PortletTiles.tsx --> Child component

function PortletTiles(props:any) {
  let addNewTile= () => {  
    // Some logic to render tile here.. then 
    // How to call parent container's arrangeTiles function?
  };
  return (
    <div>
        <button onClick={addNewTile}>Add Tile</button>
    </div>
  );
}
export default PortletTiles;

Upvotes: 1

Views: 281

Answers (2)

Jevon Cochran
Jevon Cochran

Reputation: 1774

The easiest way to go about this would be to use context API. This provides you with the ability to have state that you can reference and manipulate across different components. You can reference the docs for context API here.

import { createContext } from "react";

const AppContext = createContext();

const AppProvider = (props) => {
  

  const arrangeTiles = () => {
    // place function code here
  };

  return (
    <AppContext.Provider value={{arrangetiles}}>
      {props.children}
    </SiteContext.Provider>
  );
};

const AppConsumer = AppContext.Consumer;

export { AppContext, AppConsumer };

export default AppProvider;

Wrap your app component in the AppProvider

In the child component, you would need to import the rearrangeTiles function and then you can use it:

import { useContext } from "react";

const { rearrangeTiles } = useContext(AppContext);

Upvotes: 0

Ramesh Reddy
Ramesh Reddy

Reputation: 10662

You can create a context and pass the function or any other props as value. useContext can be used to consume the passed value from the provider.

type ContextValue = {
  arrangeTiles: () => void;
};

const Context = createContext<ContextValue>({
  arrangeTiles: () => {}
});

const StyleWrapper: FC = (props) => {
  let arrangeTiles = () => {
    // Arrange Tile logic
    alert("Tiles have been arranged!");
  };
  return (
    <Context.Provider value={{ arrangeTiles }}>
      <div id="cnplStyleWrapper">{props.children}</div>
    </Context.Provider>
  );
};

const PortletTiles: FC = (props) => {
  const { arrangeTiles } = useContext(Context);

  let addNewTile = () => {
    arrangeTiles();
  };
  return (
    <div>
      <button onClick={addNewTile}>Add Tile</button>
    </div>
  );
};

export default function App() {
  return (
    <StyleWrapper>
      <PortletTiles />
    </StyleWrapper>
  );
}

Edit hardcore-ully-risj5


If your app already uses redux, then you can move arrangeTiles to the reducer and dispatch actions from the components.

Upvotes: 1

Related Questions