简体   繁体   English

使用ReactJS从兄弟组件调用方法

[英]Call method from sibling component using ReactJS

I have one ReactJS App which I reduced to the minimum as possible on the diagram below: 我有一个ReactJS App ,我在下图中尽可能减少到最小值:

在此输入图像描述

Side note: On this App I use Redux to manage state changes. 附注:在此App我使用Redux来管理状态更改。

This App contains: App包含:

  • Component: UploadScreen with an image holder and a button. 组件:带有图像保持器和按钮的UploadScreen When that button is clicked, the user gets displayed a Popup Window which let him to pick an image from his device file system. 单击该按钮时,用户会显示一个Popup Window ,让他从设备文件系统中选择一个图像。 Then that image is displayed on the image holder. 然后该图像显示在图像持有者上。

  • Component: AuxWidget which is a totally different component (needs to be separate) which also contains a button that when it is clicked it should popup the Select File window. 组件: AuxWidget是一个完全不同的组件(需要分开),它还包含一个按钮,单击该按钮时,它应弹出Select File窗口。 I was thinking in something like triggering the click event of the first button. 我在考虑触发第一个按钮的click事件。

Any idea on how to achieve that? 有关如何实现这一点的任何想法

First I though about using Redux but I think that's not a too good idea because even though you can send messages with it from one component to another, that causes a render update and I don't want that. 首先我想使用Redux但我认为这不是一个好主意,因为即使你可以将消息从一个组件发送到另一个组件,这会导致渲染更新,我不希望这样。

Also, I was thinking on using jQuery but that's not the best approach when it comes to ReactJS . 此外,我正在考虑使用jQuery但这并不是ReactJS的最佳方法。

Also, I thought about using the attribute: ref="foo" to get a reference to the other component but I think that's normally done when you want the interaction to be between parent and child components. 此外,我考虑使用属性: ref="foo"来获取对其他组件的引用,但我认为通常在您希望交互在父组件和子组件之间时完成。

Also, I was thinking about EventEmmitter but I don't know if that's the best approach on this case (I'm using Redux to manage the state changes between components). 此外,我正在考虑EventEmmitter但我不知道这是否是这种情况下的最佳方法(我使用Redux来管理组件之间的状态变化)。

One of the best ways I can suggest using RxJS , you can create a Subject and pass it to your components. 我可以建议使用RxJS的最佳方法之一 ,您可以创建一个主题并将其传递给您的组件。 In one component you will need to subscribe to it and whenever you will call next on your subject from the second component, the other will be notified, so you can trigger open popup. 在一个组件中,您需要订阅它,并且每当您从第二个组件调用下一个主题时,另一个组件将被通知,因此您可以触发打开弹出窗口。 You can even create your own implementation for this in case you don't want to add new library to your project. 如果您不想将新库添加到项目中,您甚至可以为此创建自己的实现。

The upload window could be triggered when a certain state in the app changes. 当应用中的某个状态发生变化时,可以触发上传窗口。 The relevant state on the app could be changed from different places, like from AuxWidget and UploadScreen . 应用程序上的相关状态可以从不同的地方更改,例如AuxWidgetUploadScreen That way they are not coupled with the upload window. 这样他们就不会与上传窗口相关联。 They merely call a function that is passed to them and that function changes the state on the app and it will display the window. 它们只调用一个传递给它们的函数,该函数改变了应用程序的状态,它将显示窗口。

If you have a shared component between two unrelated component I think it is best to lift that common component and let its state sit on a higher level. 如果您在两个不相关的组件之间有共享组件,我认为最好提升该公共组件并让其状态处于更高级别。

If I understand things correctly, your primary concern is code-reuse as opposed to wanting to call a sibling method. 如果我理解正确,那么你主要关注的是代码重用,而不是想要调用兄弟方法。 Basically, you want a SelectFilePopup component that can be re-used (open/closed) cleanly. 基本上,您需要一个可以干净地重复使用(打开/关闭)的SelectFilePopup组件。 I think React Portals could be a good solution for this. 我认为React Portals可能是一个很好的解决方案。 I found a good example ( https://github.com/Assortment/react-modal-component/blob/master/src/components/Modal.js ) of how a Modal can be isolated into a component and be called anywhere in the codebase. 我找到了一个很好的例子( https://github.com/Assortment/react-modal-component/blob/master/src/components/Modal.js ),了解如何将Modal隔离到一个组件中并在其中的任何位置调用代码库。

The usage of the Modal looks like this (copied and slightly modified from App.js in the github project above) Modal的用法看起来像这样(从上面的github项目中的App.js复制并稍加修改)

import Modal from './components/Modal';
<Modal><div>Click me to open Modal</div></Modal>

And the Modal component implementation (simplified) 和Modal组件实现(简化)

render() {
    return (
        <Fragment>
            <ModalTrigger
                onOpen={this.onOpen}
            />
            {isOpen &&
                <ModalContent/>
            }
        </Fragment>
    )   
}    

By default the Modal component shows a trigger (ie button) when isOpen state is false. 默认情况下,当isOpen状态为false时,Modal组件显示触发器(即按钮)。 Once clicked, and isOpen switches to true, the ModalContent (ie can be the FilePickerPopup) is dynamically created and attached to document body. 单击后,isOpen切换为true,ModalContent(即可以是FilePickerPopup)动态创建并附加到文档正文。 You can check out the source code for more details. 您可以查看源代码以获取更多详细信息。 I think its a very clean solution to modals. 我认为它是一种非常干净的模态解决方案。 So in your case, your code could end up looking something like this 因此,在您的情况下,您的代码最终可能会看起来像这样

UploadScreen.js UploadScreen.js

import FileSelectPopup from './components/FileSelectPopup';
<FileSelectPopup>{Upload Image}</FileSelectPopup>

AuxWidget.js AuxWidget.js

import FileSelectPopup from './components/FileSelectPopup';
<FileSelectPopup>{Upload Image or some other text}</FileSelectPopup>

So basically, AuxWidget doesn't even need to know about where the FileSelectPopup is located at. 所以基本上,AuxWidget甚至不需要知道FileSelectPopup的位置。 It's an independent component that can be called anywhere. 它是一个可以在任何地方调用的独立组件。 The caveat is that the Modal implementation in the project I linked to is not a singleton (although it can be modified to be one). 需要注意的是,我链接到的项目中的模态实现不是单例(尽管它可以修改为一个)。 So if AuxWidget and UploadScreen are visible to the user at the same time, clicking both Upload Image buttons will create two instances of the Popup. 因此,如果AuxWidget和UploadScreen同时对用户可见,则单击“上载图像”按钮将创建两个Popup实例。

我将在父组件中定义该函数,并将其作为props传递给两个子组件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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