简体   繁体   中英

how to pass an event from a child component to parent component back down to another child in React

Lets say for instance that I have three components in React, an App (the parent component), a button component and a component that is meant to display something, can be anything doesn't really matter. Lets say in the button component is activated, how would I pass the information (ie that the event actually happened) to the App parent component back down to the other child component to let it know a specific event happened to display some message?

this is how I would go about dong this using hooks :

const Parent=(props)=>{
 [eventHappend,setEventHappend]=useState(false)
 return (
  <div>
     <Child1 setEventHappend={setEventHappend} />
     <Child2 eventHappend={eventHappend} />
  </div>
)
}


const Child =({setEventHappend})=>{
 return (
  <div>
     <button onClick={e=>setEventHappend(true)} > click me 1 </button>
  </div>
)
}


const Child2 =({eventHappend})=>{
 
 return (
  <div>
     <button onClick={e=>{/* some code*/ }} > {eventHappend?'event happend':'event didnt happen yet '} </button>
  </div>
)
}

There are various ways you can achieve this pass state as props to the child elements (must know before other methods), context or use redux which has a store.

Generally speaking. React has one way data flow, uni directional. As in the parent will hold the state and will be passed to child elements.

Here App holds the state buttonClick which has the information about the event.

const App = () => {
const [ buttonClick, setButtonClick] = React.useState(false);
const messageToBeDispalyed = "The button has been clicked"
return (
<div>
<CustomButton setEventHappened={setButtonClick} />
<DisplayText  value = {buttonClick ? messageToBeDispalyed : ""} />
</div>
 )
}

const CustomButton = (props) =>{
return <button onClick={(e)=>props.setEventHappened(true)} >  Click Me </button>
}

const DisplayText = (props) => {
return <h1> {props.value} </h1>
}


Similar answers to the others, but you would pass down a method to the child from the parent to update the state. But be aware that by doing this will cause a rerender for all of the parent's children.

const Parent = () => {
  const [state, setState] = React.useState(false);

  const handleClick = value => {
    setState(value);
  };

  return (
    <Child state={state} handleClick={handleClick} />
    <OtherChild isTrue={state} /> // this component needs data changed by <Child />
  )
};
const Child = props => {
  const {state, handleClick} = props;

  return (
    <button onClick={() => handleClick(!state)} >click me</button>
  );
};

This way the parent alone handles the state change and provides that method to the child.

as @Loveen Dyall and @Shruti B mentioned you can use RXJS for a more modular approach ,While RxJS is typically thought of as being used with Angular projects, it's a completely separate library that can be used with other JavaScript frameworks like React and Vue.

When using RxJS with React, the way to communicate between components is to use an Observable and a Subject (which is a type of observable), I won't go too much into the details about how observables work here since it's a big subject, but in a nutshell there are two methods that we're interested in: Observable.subscribe() and Subject.next(). learn more about RXJS and Observables : https://blog.logrocket.com/understanding-rxjs-observables/
Observable.subscribe() The observable subscribe method is used by React components to subscribe to messages that are sent to an observable.

Subject.next() The subject next method is used to send messages to an observable which are then sent to all React components that are subscribers (aka observers) of that observable.


here is how you implement it in this use case : this is called a service and you would put this file in a services folder
import { eventsService} from '../services';
const Child1 =()=>{
  const [child2EventFired,setChild2EventFired]=useState(false)
  useEffect(()=>{
      let subscription = eventsService.getEventNotification().subscribe(eventTitle => 
          {
            if (eventTitle=="CHILD2_BUTTON_CLICK" ) {
               setChild2EventFired(true)
            }else{
                setChild2EventFired(false)
             }
        });
      return ()=>{
       subscription.unsubscribe();
     }
    },[])

    return <div>
         <button> {child2EventFired? 'child2 button event fired':'event not fired yet'} </button>
    </div> 
}

in your Child 1 component you would subscribe to the observable in useEffect or compoentDidMount if your using class component:

import { eventsService} from '../services';
const Child2 =()=>{
    Child2Click=(e)=>{
        //some code, 
        //then send messages to the observable observable
        eventsService.sendEvent('CHILD2_BUTTON_CLICK');
    }

    return <div>
         <button onClick={Child2Click} >click me</button>
    </div> 
}

in your Child 2 component

import { eventsService} from '../services'; const Child2 =()=>{ Child2Click=(e)=>{ //some code, //then send messages to the observable observable eventsService.sendEvent('CHILD2_BUTTON_CLICK'); } return <div> <button onClick={Child2Click} >click me</button> </div> }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM