是否可以公开 React 函数组件中定义的函数以在其他组件中调用?
我正在重构警报小部件的一些旧代码,并将其抽象为使用 DOM 门户和条件渲染的自己的组件。我希望尽可能多地保留该组件内部的工作,因此理想情况下,我希望能够公开 Alert 组件本身以及该组件内部定义的函数来触发渲染状态和样式动画这样就不需要外部状态管理。我想要做的事情是这样的:
import Alert, { renderAlert } from '../Alert'
const CopyButton = () => (
<>
<Alert text="Text copied!" />
<button onClick={() => renderAlert()}>Copy Your Text</button>
</>
)
这是我目前为 Alert 组件所做的事情 - 现在它从外部接收一个状态变量,当单击按钮时该状态变量会翻转并触发 useEffect
在 Alert 内部触发 renderAlert
函数。我希望直接从组件公开 renderAlert
,这样我就可以调用它,而无需像上面那样使用额外的状态变量。
const Alert = ({ label, color, stateTrigger }) => {
const { Alert__Container, Alert, open } = styles;
const [alertVisible, setAlertVisible] = useState<boolean>(false);
const [alertRendered, setAlertRendered] = useState<boolean>(false);
const portalElement = document.getElementById('portal');
const renderAlert = (): void => {
setAlertRendered(false);
setAlertVisible(false);
setTimeout(() => {
setAlertVisible(true);
}, 5);
setAlertRendered(true);
setTimeout(() => {
setTimeout(() => {
setAlertRendered(false);
}, 251);
setAlertVisible(false);
}, 3000);
};
useEffect(() => {
renderAlert();
}, [stateTrigger])
const ele = (
<div className={Alert__Container}>
{ alertRendered && (
<div className={`${Alert} ${alertVisible ? open : ''}`}>
<DesignLibAlert label={label} color={color}/>
</div>
)}
</div>
);
return portalElement
? ReactDOM.createPortal(ele, portalElement) : null;
};
export default Alert;
I'm refactoring some old code for an alert widget and am abstracting it into its own component that uses DOM portals and conditional rendering. I want to keep as much of the work inside of this component as I possibly can, so ideally I'd love to be able to expose the Alert component itself as well as a function defined inside of that component triggers the render state and style animations so that no outside state management is required. Something like this is what I'm looking to do:
import Alert, { renderAlert } from '../Alert'
const CopyButton = () => (
<>
<Alert text="Text copied!" />
<button onClick={() => renderAlert()}>Copy Your Text</button>
</>
)
Here's what I currently have for the Alert component - right now it takes in a state variable from outside that just flips when the button is clicked and triggers the useEffect
inside of the Alert to trigger the renderAlert
function. I'd love to just expose renderAlert
directly from the component so I can call it without the additional state variable like above.
const Alert = ({ label, color, stateTrigger }) => {
const { Alert__Container, Alert, open } = styles;
const [alertVisible, setAlertVisible] = useState<boolean>(false);
const [alertRendered, setAlertRendered] = useState<boolean>(false);
const portalElement = document.getElementById('portal');
const renderAlert = (): void => {
setAlertRendered(false);
setAlertVisible(false);
setTimeout(() => {
setAlertVisible(true);
}, 5);
setAlertRendered(true);
setTimeout(() => {
setTimeout(() => {
setAlertRendered(false);
}, 251);
setAlertVisible(false);
}, 3000);
};
useEffect(() => {
renderAlert();
}, [stateTrigger])
const ele = (
<div className={Alert__Container}>
{ alertRendered && (
<div className={`${Alert} ${alertVisible ? open : ''}`}>
<DesignLibAlert label={label} color={color}/>
</div>
)}
</div>
);
return portalElement
? ReactDOM.createPortal(ele, portalElement) : null;
};
export default Alert;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尽管“访问”其他组件并调用函数并不常见,但 React 确实允许“后门”这样做。
这个想法是强制公开
renderAlert
函数通过 React 参考系统。示例:
...
实现此目的的一种更 React 的方式可能是将 Alert 状态抽象到一个 AlertProvider 中,该 AlertProvider 呈现门户并处理警报的呈现,并通过以下方式提供
renderAlert
函数:这 语境。示例:
...
...
Though it's not common to "reach" into other components and invoke functions, React does allow a "backdoor" to do so.
The idea is to expose out the
renderAlert
function imperatively via the React ref system.Example:
...
A more React-way to accomplish this might be to abstract the Alert state into an AlertProvider that renders the portal and handles the rendering of the alert and provides the
renderAlert
function via the context.Example:
...
...