React – 将事件从 child 组件传递到 parent
React – Passing event from child component to parent
我是 React.js 的新手,如果这是一个愚蠢的问题或之前有人问过,我深表歉意。我有一个组件树结构如下: form (grandparent) → input field (parent) → button (child)
我正在尝试监听 按钮 的点击(onClick 事件处理程序),并在 表单 (理想情况下也将输入字段的内容传递给表单)。
是否有执行此操作的通用方法或我应该阅读的文档的特定部分?我知道我可以通过 props 将数据从 parent 传递到 child,这有相反的做法吗?
您可以让表单将函数作为 prop 传递给子项,然后让子项将该函数作为 prop 传递给按钮,如下所示:
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.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
对于这个简单的例子,我只是在每次渲染 Example
时重新创建函数,但有时你不想这样做,因为它使 Parent
和 button
两者 re-render 随时 Example
中的任何内容发生变化。您可以使用 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 components were memoized, as with React.memo
or [for class
components] PureComponent
or a component using shouldComponentUpdate
.) More about that in my other answers and .
这里展示了更改与点击处理程序无关的内容如何导致不必要的 re-rendering 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.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
还有一个示例,它记录了 onClick
并使用 React.memo
使 Parent
而不是 re-render 当没有什么重要的(对它)改变时:
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.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
我是 React.js 的新手,如果这是一个愚蠢的问题或之前有人问过,我深表歉意。我有一个组件树结构如下: form (grandparent) → input field (parent) → button (child)
我正在尝试监听 按钮 的点击(onClick 事件处理程序),并在 表单 (理想情况下也将输入字段的内容传递给表单)。
是否有执行此操作的通用方法或我应该阅读的文档的特定部分?我知道我可以通过 props 将数据从 parent 传递到 child,这有相反的做法吗?
您可以让表单将函数作为 prop 传递给子项,然后让子项将该函数作为 prop 传递给按钮,如下所示:
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.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
对于这个简单的例子,我只是在每次渲染 Example
时重新创建函数,但有时你不想这样做,因为它使 Parent
和 button
两者 re-render 随时 Example
中的任何内容发生变化。您可以使用 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 components were memoized, as with React.memo
or [for class
components] PureComponent
or a component using shouldComponentUpdate
.) More about that in my other answers
这里展示了更改与点击处理程序无关的内容如何导致不必要的 re-rendering 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.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
还有一个示例,它记录了 onClick
并使用 React.memo
使 Parent
而不是 re-render 当没有什么重要的(对它)改变时:
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.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>