Embedded Component Not Updating - javascript

I am working on a React Native project, and I am currently focused in the Chatroom aspect. Due to user roles, this component is embedded in another component for 2 of the 3 user types, but navigated to (not embedded in anything other than App.js) for the other type.
This means sometimes the app uses the props it was supplied with, and other times it uses the props.route.params?.item syntax to extract information. As is such its difficult to maneuver with useEffects to make sure it works on both sides.
The issue I am facing is with the embedded version of this component. It takes three props, the chatroom, and two booleans that are unrelated to this. The chatroom can change as a GUARDIAN user can see their CHILD user's messages, but they cannot text in them (those are the other two boolean values). From the parent component, users can toggle whether they are the Guardian accessing their own chat, or if they want to view their children' chats. While the all three values change properly (I console.log'd this in the parent component to confirm) the chatroom does not change inside of the embedded component.
I will show you what I mean...
// PARENT COMPONENT //
function renderMessageThread(chat){
console.log("\n\n\n", chat[0].messages.length, "LANDING")
console.log(msgUser.id, isThisChatMine())
return <MessageThread hardCodedChat={chat} hardCoderUserId={msgUser.id} isItMe={isThisChatMine()} />
}
The console.logs show the proper values. Inside the MessageThread component, both hardCoderUserId and isItMe are correct values, even when isItMe changes values. hardCodedChat, however, never has its value changed from the first time it is created. Does anyone have any ideas on how to have this changes as well?

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.

Prevent Vue.js re-rendering child components

I've got a complex component which does all its rendering in a render function. There are multiple parts to this, and different bits of the view get rendered - one of these things is a filter bar, showing the filters that have been applied.
What I'm noticing happening, is if I apply a filter which in turn presents this bar, it causes everything else to be fully re-rendered. This is causing a number of other issues and I need to try and stop it from happening.
I've never come across this issue when using normal templates as Vue seems to handle these very intelligently, but I have no idea how to tackle this. The only thing I can think of is setting a key on each thing I don't want re-rendered but not sure if this will a) solve the problem, and b) be possible for the content that is passed in through a slot
Has anyone else faced this issue, and if so how can it be solved?
I had a similar issue when using vuetify text inputs in a complex component which was causing the app to slow down drastically.
In my search I found this link which was specific to vuetify:
high performance impact when using a lot of v-text-field
then found out that this is actually a vue thing from this GitHub issue:
Component with slot re-renders even if the slot or component data has not changed
and there is plan to improve this in it is tracked here (vue 3 should resolve this issue):
Update slot content without re-rendering rest of component
so after reading through all these I found some workarounds that helped me a lot to boost the performance of my app, I hope these will help you as well:
divide that complex component into smaller ones specially when there is some bit of code that changes data that bounds to template causing re-rendering (put them in their own component)
I moved all data layer control to the vuex store, instead of using v-model every where and passing data as events and props, all the data is updating in the store through an action and read from the store through a getter. (from data I mean somethings that is being looped in the template in a v-for, API results, and so on... all of them is being set, updated and read through the store. my components still have the data object but only for the things related to the style and template control like a boolean to control a modal or an imported icon which is used in the template and alikes)
lastly I wrote a function called lazyCaller which its job is to update the values in the store with a delay (when immediate data update isn't necessary) to avoid rapid updates comping from something like a text input (with out this every key stroke trigger the value update action)

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

Force Ember component to re-render from within its route

We develop an Ember based framework for internal use of various groups within our organization. Along with this, we maintain a demo page, which displays all the components we've developed along with documentation on how to use the components. I need to modify one of the component demo pages, to allow the user to custom build the component. For example, the component has two properties showCheckboxes and showRadioButtons. By default, showCheckboxes is true, and the component, of course, displays checkboxes. I want to add a select so the user can choose between radio buttons and checkboxes. Everything is wired up correctly and the routes action gets called, but, if I select radioButtons, the component does not refresh and display readio buttons. I've set breakpoints and I see that the route is not called, so the new properties are not read. How can I force Ember to rebuild the component from scratch? I've tried this.refresh() in the route, I've tried setting the model to the new model with the changes, but the component does not redraw with the new properties. I've also tried transitionTo. But if I don't pass a model, nothing happens. But if I pass in the new route, I get this error:
Error: More context objects were passed than there are dynamic segments for the route
I hope this was clear enough for someone to provide some guidance.
Thanks

How to set the context of a EmberJS component?

I found on this page a great example of https://github.com/emberjs/ember.js/issues/11043 how to inherits from a component. Here is the example: http://emberjs.jsbin.com/rwjblue/443/edit?html,css,js,output
I played a bit with and especially with actions and come to this question:
How can I set the context of the component?
Consider the following examples:
http://emberjs.jsbin.com/cofobanoca/edit?html,css,js,output
and a derivate of it
http://emberjs.jsbin.com/gipawemipe/1/edit?html,css,js,output
They are pretty much the same except that in the second link, the component is dynamically create inside an action.
My question is, why is {{this}} in the second example a "generated application controller" and not a "App.XBarComponent"?
EDIT:
Maybe I was not clear.
What I want to achieve is to render a modal which contains inputs fields. This should be rendered inside the application template (using outlet) as a popup over the whole page. The Modal is built with two components just like foo and bar. BaseModal (which is Foo) and LoginModalContent (which is Bar) are better names.
On click on OK (which is defined in BaseModal), I want to call the OK action of LoginModalContent to be able to get the values of the forms (defined in LoginModalContent) using e.g. this.get('username').
They are pretty much the same except that in the second link, the
component is dynamically create inside an action.
There you're not creating a component, just rendering a view, and if you don't specify a controller for a view Ember creates one for you, that's why {{this}} is "generated application controller" in the second example.
That also explains why the action handler of the XBarComponent doesn't work in the second example, since the view is missing the component controller.
If you want to programatically insert components the component helper is your best bet, it renders components by its name while letting Ember handle the view/controller/subcomponents management.

Categories