React Native/Expo: Event Emitter between screens; trigger refresh - javascript

I've scoured this site and various Github issues for a solution but am still a bit stuck. In essence, this is the flow that I desire:
Land on first component/screen, which has some information
Click a button and be pushed to a second component/screen
Do something on this second component/screen
Pop back to first component/screen
Have refreshed information be displayed when we come back to this page
Issues:
Component lifecycles don't work because when I'm popping from the second component to the first component (the parent), there's no component lifecycle method I can call in this case.
Event Emitters won't suffice as a solution because they only work within a single component (is this correct btw?)
Would greatly appreciate any help I can get. Thank you!

In the first component, create a function that will refresh the component by updating the state. Pass the function to the second component and when you pop, call this function.

Related

Calling Video and Audio Calling components in React

I have two components and being called after one another. The issue is if I call both components without any condition then the functionality of both components gets intermixed. I used the following condition to run both components.
{amIVoiceCalling?<VoiceCall amIVoiceCalling={amIVoiceCalling}/>:null}
{amICalling? <VideoCall amICalling={amICalling}} />:null}
"amIVoiceCalling" gets true when user clicks the voice-call icon whereas "amICalling" gets true when the user clicks on the video-call icon. In this case, the problem comes on the receiver side because the user who would receive the audio/video call never changes the above mentioned states so the components dont run for him. Any ideas please. Thanks in anticipation.

Call method from sibling component using ReactJS

I have one ReactJS App which I reduced to the minimum as possible on the diagram below:
Side note: On this App I use Redux to manage state changes.
This App contains:
Component: UploadScreen with an image holder and a button. When that button is clicked, the user gets displayed a Popup Window which let him to pick an image from his device file system. 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. I was thinking in something like triggering the click event of the first button.
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.
Also, I was thinking on using jQuery but that's not the best approach when it comes to 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.
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).
One of the best ways I can suggest using RxJS, you can create a Subject and pass it to your components. 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. 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. I think React Portals could be a good solution for this. 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.
The usage of the Modal looks like this (copied and slightly modified from App.js in the github project above)
import Modal from './components/Modal';
<Modal><div>Click me to open Modal</div></Modal>
And the Modal component implementation (simplified)
render() {
return (
<Fragment>
<ModalTrigger
onOpen={this.onOpen}
/>
{isOpen &&
<ModalContent/>
}
</Fragment>
)
}
By default the Modal component shows a trigger (i.e button) when isOpen state is false. Once clicked, and isOpen switches to true, the ModalContent (i.e can be the FilePickerPopup) is dynamically created and attached to document body. 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
import FileSelectPopup from './components/FileSelectPopup';
<FileSelectPopup>{Upload Image}</FileSelectPopup>
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. 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.
I would define the function in the parent component and pass it to both children as props

React Native navigation.goBack() inside componentDidUpdate

I am trying to call the navigation.goBack() inside componentDidUpdate, the backing works however the animation of going back does not. Like the slide effect.
The use case that I have is for implementing an edit screen. Suppose you just edited some items but now when you click update/save you want to go back. In order to catch that update/save event, I am making it a part of the NavigationScreenProp, this is setting the state of the NavigationScreenProp.
Once the header update button is clicked the NavigationScreenProp becomes {isUpdated=true}. This fires the componentDidUpdate event and inside of it I handle saving the data, however the problem occurs when calling the back.
This scenario however works if you create an alert when isUpdated===true and goes back with animation.
Any help or direction would be great help! Thanks!
Also if there is a better way to handle this scenario, please comment :)

React.js call components into setState

I'm trying to make a toaster component.
https://codesandbox.io/s/62n81oy4pr
in index.js, this.setState({ toasterText: "Room added to summary." });
from this code, you can change the value of the toaster whatever you want and When you click the button several times, the toaster keeps showing and then disappear after 2.6 sec from the last click.
However, When I set a component (or even a div) into the 'toasterText' and click the button,
something like this,
this.setState({ toasterText: <Component>asdfasdf</Component> });
the toaster appear by one click and disappear as soon as I click the button again.
I think I can do something with the componentDidUpdate or am I just not allowed to set components in setState??
sorry for my bad English.
The reason it "disappears" is because the component is re-mounted (destroyed and re-created), as opposed to re-rendered (text updated) in your first example.
While it is technically possible to do this, it is considered anti-pattern for numerous reasons (the problem you experienced being one of them). I can't think of any reason you'd ever want to take that approach; just stick with updating the text.
If you really have to implement the second approach, try adding a key prop to the component. That should prevent the re-mounting behavior.

Reactjs component.setProps() alternative, how to send variable to detached element

I am using things like:
var MUSIC = React.renderComponent( Music({ }), document.getElementById("music-div"))
to later in the script, in an independent element (so not parent of MUSIC) do:
MUSIC.setProps({ url: 'http://...' })
to send a song to de music player, which is detached from the rest, so it does not accidentally gets refreshed by react, because it was programmatically generated (wavesurferjs)
Fine, however, the recent few updates (.11.x) have apparently deprecated that. I do understand where they are coming from, it fits the whole React logic.
However, how will we now ever programmatically modify state/props from outside? Even when I want to talk directly to the parent, which should be allowed.
The changelog tells me in this case the MUSIC variable would have become a descriptor, however, in consoles out the exact same object as far as I can tell. And the documentation says nothing about this descriptor and even less about alternative possibilities.
(http://facebook.github.io/react/blog/2014/07/17/react-v0.11.html#descriptors)
So, if I have two divs
<div id="main-div"> <button></button></div>
<div id="music-div"> </div>
And want to keep them separate, how would I go about giving two parallel parents each-other props?
I don't want to put both in one react div, which would not even solve my problem, because, how would the button in main-div give the props to music-div?
Or would their conceived alternative be to just create a new instance on that id and hope it diffs to 0?
The update states:
"You could store that reference and then call functions on it (eg
component.setProps(...)). This no longer works."
However, that still does work, with (0.11.1) so I don't understand what they are talking about?
You've got several options.
Wrap both main-div and music-div with an "Application" component. Pass a handler down that changes its state so the div's are re-rendered.
Use an event bus to dispatch and listen to events. Basically a component exposes its private setState/setProps() methods to the event bus in a listener. The other component dispatches an event that triggers that listener.

Categories