最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React – Passing event from child component to parent - Stack Overflow

programmeradmin2浏览0评论

I am new to React.js so I apologise if this is a foolish question or one that has been asked before. I have a ponent tree structured as such: form (grandparent) → input field (parent) → button (child)

I am attempting to listen for a click (onClick event handler) of the button and have that trigger a function at the level of the form (ideally also passing the content of the input field to the form).

Is there a general method to do this or a specific part of the documentation I should read? I know I can pass data from the parent to child via props, is there a reverse of this?

I am new to React.js so I apologise if this is a foolish question or one that has been asked before. I have a ponent tree structured as such: form (grandparent) → input field (parent) → button (child)

I am attempting to listen for a click (onClick event handler) of the button and have that trigger a function at the level of the form (ideally also passing the content of the input field to the form).

Is there a general method to do this or a specific part of the documentation I should read? I know I can pass data from the parent to child via props, is there a reverse of this?

Share Improve this question asked Feb 20, 2022 at 15:07 BenBen 5031 gold badge7 silver badges19 bronze badges 3
  • Hi! Please update your question with a minimal reproducible example demonstrating the problem, ideally a runnable one using Stack Snippets (the [<>] toolbar button). Stack Snippets support React, including JSX; here's how to do one. It's impossible for an input field to have a button in it if you really mean input and button. So an example would make things a lot clearer. – T.J. Crowder Commented Feb 20, 2022 at 15:09
  • I answered a similar question earlier today. – よつば Commented Feb 20, 2022 at 15:14
  • in terms of docs, it sounds like this could help: react docs and free code camp. – daniel Commented Feb 20, 2022 at 15:25
Add a ment  | 

1 Answer 1

Reset to default 3

You'd have the form pass a function to the child as a prop, and have the child pass that function on to the button as a prop, like this:

const {useState} = React;

const Example = () => {
    const onClick = () => {
        console.log("Clicked!");
    };
    return <Parent onClick={onClick} />;
};

const Parent = ({onClick}) => {
    return <button type="button" onClick={onClick}>Click Me</button>;
};


ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare./ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

For that simple example, I've just recreated the function every time Example is rendered, but there are times you don't want to do that, because it makes Parent and button both re-render any time anything in Example changes. You might use useCallback or useMemo to avoid passing a new function to Parent (and thus to button) every time. (That would only help if Parent and any other intermediate ponents were memoized, as with React.memo or [for class ponents] PureComponent or a ponent using shouldComponentUpdate.) More about that in my other answers here and here.

Here's something demonstrating how changing something unrelated to the click handler causes unnecessary re-rendering of Parent:

const { useState, useEffect } = React;

const Example = () => {
    const [counter, setCounter] = useState(0);
    useEffect(() => {
        const handle = setInterval(
            () => setCounter(c => c + 1),
            800
        );
        return () => {
            clearInterval(handle);
        };
    }, []);
    const onClick = () => {
        console.log("Clicked!");
    };
    return <div>
        <div>
            Counter: {counter}
        </div>
        <Parent onClick={onClick} />
    </div>;
};

const Parent = ({onClick}) => {
    console.log(`Parent rendering...`);
    return <button type="button" onClick={onClick}>Click Me</button>;
};


ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare./ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

And an example that memoizes onClick and uses React.memo to make Parent not re-render when nothing significant (to it) changes:

const { useState, useEffect, useCallback } = React;

const Example = () => {
    const [counter, setCounter] = useState(0);
    useEffect(() => {
        const handle = setInterval(
            () => setCounter(c => c + 1),
            800
        );
        return () => {
            clearInterval(handle);
        };
    }, []);
    const onClick = useCallback(() => {
        console.log("Clicked!");
    }, []);
    return <div>
        <div>
            Counter: {counter}
        </div>
        <Parent onClick={onClick} />
    </div>;
};

const Parent = React.memo(({onClick}) => {
    console.log(`Parent rendering...`);
    return <button type="button" onClick={onClick}>Click Me</button>;
});


ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare./ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

发布评论

评论列表(0)

  1. 暂无评论