Dante1021
Dante1021

Reputation: 374

Access a function from a Component in another Component in React

I am totally blank on how to use a function that is inside a component and needs to be used in another component.

Here is a simple program:

Test.js

export default function Test(){
  const testFunc = () => {
   console.log("it is working")
}
return(
  <div>
   Hi
</div>
)
}

Test2.js

export default function Test2(){
  
return(
  <button onClick={}> // Here I want to use testFunc() from Test file
   Click
</button>
)
}

Could someone please explain how can it be achieved to access the function in Test2 file. Thanks in advance!!

Upvotes: 1

Views: 5554

Answers (6)

Lavkush
Lavkush

Reputation: 1

Well you can use combination of useEffect and global state management.

Define that function inside useEffect and define one global state using any state management library and pass this state as dependency. now rather than calling that function from anyware just update this dependency state from anywere and useEffect will take care of calling that function.

I have recently used this for showing popup when user is filling some form and they have modified state and they try to navigate to somewhere else in the application.

Upvotes: 0

Konrad
Konrad

Reputation: 24661

Solution

Usually, context is used to share the same state between many components that aren't in parent-children relations. codesandbox

Creating context

First, create a context:

const MyContext = createContext();

And context provider:

const MyContextProvider = ({ children }) => {
  const [myState, setMyState] = useState(0);

  return (
    <MyContext.Provider value={{ myState, setMyState }}>
      {children}
    </MyContext.Provider>
  );
};

And context hook (for convenience):

const useMyContext = () => useContext(MyContext);

Using context

Remember to use the provider in the common ancestor of the components:

function App() {
  return (
    <MyContextProvider>
      <Component1 />
      <Component2 />
    </MyContextProvider>
  );
}

Create your components:

function Component1() {
  // as you can see, you can access the function here
  const { setMyState } = useMyContext();
  return (
    <button onClick={() => setMyState((state) => state + 1)}>click me</button>
  );
}

function Component2() {
  // and the value here
  const { myState } = useMyContext();
  return myState;
}

Upvotes: 1

jasonmzx
jasonmzx

Reputation: 517

As Konrad said in the comments, this can't be possible since these 2 components lack no relationship (Neither Components are rendering or calling each other within)

Something you could do is Render the Test2.js component within Test.js and add a callback like so:

Test.js

import Test2 from '...';

export default function Test(){
  const testFunc = () => {
   console.log("it is working")
}


return(
  <div>
   Hi
   <Test2 callbackProp={testFunc} />
</div>
)
}


Test2.js

export default function Test2({callbackProp}){
  
return(
  <button onClick={() => {callbackProp();} }> // Here I want to use testFunc() from Test file
   Click
</button>
)
}

Now whenever Test.js is rendered, it will also render Test2 (Since Test is rendering a Test2 Component) but whenever you click the button within Test2, it will execute the callback which is a function passed from Test

Nonetheless though, it's impossible to call any functions from another Component without passing down a prop like this (for future reference)

Upvotes: 3

Jonas Gr&#248;nbek
Jonas Gr&#248;nbek

Reputation: 2019

Welcome to the React community.

To use a function that is inside a component and needs to be used in another component.

You need a common parent, that handles the function.

Let's say you have the following structure.

export const ParentComponent = () => {
    return <>
        <Test1 />
        <Test2 />
    <>
}

If you want some function in Test1 to affect Test2, then you do what in react is called lifting state up https://reactjs.org/docs/lifting-state-up.html

ParentComponent

export const ParentComponent = () => {
    const [value, setValue] = useState('')
    return <>
        <Test1 setValue={setValue} />
        <Test2 value={value} />
    <>
}

Test1

export const Test1 = (props) => {
    return <>
        <input onChange={(e) => props.setValue(e.target.vale} />
    <>
}

Test2

export const Test2 = (props) => {
    return <p>{props.value}</p> 
}

When a component renders another component, it is called the parent of the rendered child. Imagine React as a tree data structure where the App.tsx/jsx will be the tree's root.

Inspecting the code above, we can see that we have a function held in the parent. This is the function you would probably consider putting in Test1. However, if you need to use it in another component, that is not a child of the current element. You will need to find the nearest common parent and pass the functionality down like in the example above.

I hope it makes sense. If not, I recommend glancing at the Main Concepts part of the official React documentation. https://reactjs.org/docs/getting-started.html

Upvotes: 2

elguapo
elguapo

Reputation: 175

You can either pass it down from a parent component, shown below, or you can use a custom hook

Parent Component:

import Child from './Child.js'
export default function Parent() {
  
  const functionToBePassed = () => { ... }

  return (
    <Child func={functionToBePassed}>
  )
}

Or you can do it via a custom hook

Two files, first one is the hook

export default function useFunc() {
  const functionToBeShared = () => {...}

  return { functionToBeShared }
}

//this is any component that wants to use the hook
import useFunc from ./useFunc;
export default function ComponentThatUsesHook() {
  const {functionToBeShared} = useFunc();
}

Upvotes: 2

Colin Hale
Colin Hale

Reputation: 870

You will want to pass the function as a prop to the child component. You can't or I should say shouldn't pass a prop to a parent, you can do this but is not a react way and never recommended. What you would do in this case is but the logic in the parent because both siblings are needing access to it.

const App = () => {
    const clickHandler = () => {
        alert("Click event")
    }
 return (
    <div className="App">
        <ChildOne clickHandler={clickHandler}/>
        <ChildTwo clickHandler={clickHandler}/>
    </div>
 )
}

}

Upvotes: 2

Related Questions