Как я могу прослушать событие, которое происходит в дочернем компоненте дочернего компонента?
В приведенном ниже примере, как я могу обработать событие «ChildLevel2 — button — onClick» в «MainComponent»?
function MainComponent() {
return (
<>
<ChildLevel1/>
</>
);
}
function ChildLevel1() {
return (
<>
<ChildLevel2/>
</>
);
}
function ChildLevel2() {
return (
<>
<button>Click-me!</button>
</>
);
}
вы можете создать функцию onClick внутри основного компонента и передать ее ChildLevel2 в качестве реквизита.
@Тони, ты имеешь в виду Main -> ChildLevel1 -> ChildLevel2?
чтобы показать пример того, что предлагают комментарии:
const MainComponent = () => {
const handleNestedEvent = (e) => {
console.info('handling event in top level component', e);
}
return (
<ChildLevel1 onNestedEvent = {handleNestedEvent}/>
)
}
const ChildLevel1 = ({ onNestedEvent }) => {
return <ChildLevel2 onNestedEvent = {onNestedEvent}/>
}
const ChildLevel2 = ({ onNestedEvent }) => {
return <button onClick = {onNestedEvent}>Click Me</button>
}
вместо этого можно использоватьContext: реагировать на контекстные документы
или Redux: React Redux docs
Вот несколько возможных способов
1. Передача функции как реквизита. Это может стать головной болью, если вам придется передать ее слишком глубоко. Думаю, всего 2 уровня — это нормально.
function MainComponent(){
const handleButtonClick = (data) => {
console.info('from child2', data);
};
return (
<React.Fragment>
<ChildLevel1 onButtonClick = {handleButtonClick}/>
</React.Fragment>
);
};
function ChildLevel1({onButtonClick}){
return (
<React.Fragment>
<ChildLevel2 onButtonClick = {onButtonClick}/>
</React.Fragment>
);
};
function ChildLevel2({onButtonClick}){
return (
<React.Fragment>
<button onClick = {() => onButtonClick('passed data')}>Click-me!</button>
</React.Fragment>
);
}
ReactDOM.render(<MainComponent />, document.getElementById("app"));
<script crossorigin src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "app"></div>
2. Использование контекстного API. createContext , useContext. Подобно централизованному состоянию, оно работает лучше, если оно слишком глубоко вложено, и вам не придется продолжать передавать его в качестве реквизита.
const ButtonClickContext = React.createContext(null);
function MainComponent(){
const handleButtonClick = (data) => {
console.info('from child2', data);
};
return (
<ButtonClickContext.Provider value = {handleButtonClick}>
<React.Fragment>
<ChildLevel1/>
</React.Fragment>
</ButtonClickContext.Provider>
);
};
function ChildLevel1(){
return (
<React.Fragment>
<ChildLevel2/>
</React.Fragment>
);
};
function ChildLevel2(){
const onButtonClick = React.useContext(ButtonClickContext);
return (
<React.Fragment>
<button onClick = {() => onButtonClick('passed data')}>Click-me!</button>
</React.Fragment>
);
}
ReactDOM.render(<MainComponent />, document.getElementById("app"));
<script crossorigin src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "app"></div>
продолжайте передавать реквизиты или используйте context API или Redux