I want to create a generic component that should detect required component View outside click (hide the View/dropdown, etc. when pressed outside). Basically it's for the Autocomplete Search Dropdown but I guess such functionality could be used in the future for other things.
The content should be dynamic and could be passed from any level of the app because such functionality is a common UX thing.
It shouldn't be modal that always render content at the screen center because a dropdown should be opened below its trigger, etc. So it should respect the initial component position. (In think to use onLayout/measure API of the initial position when passing the content into the Backdrop)
I researched a lot of resources and found that the one possible way is:
Create a TouchableWithoutFeedback layer (Backdrop) at the top level of the app.
make it fullscreen with/height
When dropdown is shown: render the Backdrop and onPress on it - close the dropdown & backdrop.
The main question is: How to pass a generic content into this Layer and save its relationship with the parent/props, re-render when needed, etc.?
Please, keep in mind, that the component which should pass content for this layer could be deep inside the app.
I guess it could be done via Context API, etc. but I'm not sure if it's the best possible way.
P.S. in the case of web it's a trivial task: create a fullscreen layer -> use a portal -> move content at the top level of the app -> render it at the required X\Y position and listen for the outside press.
I didn't expect that such functionality will be a problem in the case of RN.
Thanks for any help.
Related
I am using the React library, I want to add the ability to change the theme, it will look quite simple there are three buttons (or radio buttons) and when you click on one of these buttons the picture will change, the problem is the implementation and updating the page (so that the image does not disappear) I want to ask about implementation, how can I implement it? create a state and inside a state create imported names that each of them stores the picture itself? or it's a bad idea, and at the end I wanted to know how to do it so that when the page is refreshed, the picture does not disappear after changing the theme
I suggest using React Context, you would wrap your whole app in a ThemeProvider, then any component that needs to react to changes in the theme can access the current themeName value via the useContext hook. Here is a freecode blog on how to achieve what your after, using Context and CSS modules.
Just to note, this solution will not persist page refreshing, but the 2 solutions could be combined, if that is necessary. So when you change the theme, localstorage is also updated with the current theme name. On page load, you could read the theme name to configure the Context.
So I have been learning a lot about Angular lately and wanted to try something a bit different. I am wanting a fullscreen component that is comprised of a button that can call the browsers fullscreen API.
The problem is, I want this component to be disabled by default and be toggleable for display from any component.
I don't have any code to show because I am honestly unsure of where to start with this. Should I make a directive that calls a fullscreen service, which would have the enable/disable methods?
Do I only need a service with properties and then subscribe to it with the components that want access to the fullscreen component?
I expect that I am overthinking this and that it is as simple as making a component, service, directive and then calling the appropriate methods to enable or disable the component from view.
Any help would really be appreciative!
Can you separate your application into layouts (header,body,footer) and then you could place the button in the header component, so you can enter the full screen from any component, since they will all be in the body component of your app?
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
Let me start off by saying I understand you should never use refs.
With that said, I think in my scenario it is very valid. Specifically I am using a window.onscroll handler and cannot simply change props in the onscroll handler. Changing state or props in an onscroll handler rerenders child componentsfar too often, which causes way too much lag.
Hence since my scenario only requires setting the style of an element on scroll, (i.e. I make something sticky to the top of page when it is scrolled out of view), I get 0 lag by simply setting this.refs.myelement.style.position = 'fixed'
My problem is that I am currently doing:
this.refs.childelement.refs.childschildelement.refs.childschildschildselement.refs.style.position = 'fixed'
Basically I have my onscroll handler 3 parents abvoe on the actual element I want to style.
My page consists of a List component. This consists of ReadOnlyOrEditable components. Editable components are RichTextEditors which have a Toolbar Component. It is this Toolbar that I need to set the position to fixed when a window scroll event occurs.
Hence on a page I'll have some 10 ReadOnlyOrEditable components, of which maybe 5 are RichTextEditors, each having a Toolbar.
The toolbar has buttons like italics, bold, etc.
When the user scrolls down, we don't want the user to have to scroll back up if the toolbar goes out of view. I.e. so we want to set the position to be fixed if the toolbar goes out of view so that the user can hit italics / bold / etc. immediately.
So how do I make this nicer without having to pass refs from the top down? The way I currently have it is very ugly...
I prefer to keep the onscroll handler close to the location of the list because having window.onscroll handlers in each Toolbar component implies I am setting multiple window.scroll handlers which is unnecesary work on the browser.
Any suggestions is gladly welcome.
Like everything, I believe there are many ways to solve one problem and here's how I would tackle it.
I would abstract the responsibility of registering/unregistering to a node scroll events and firing custom events at predetermined positions to a "service".
The scrollable component or the app container (List component?) would be the glue between the scroll notification service and its children
The scrollable component would pass in a custom registration function to its children via props. This custom registration function would receive the node (Toolbar) to monitor for positions and a callback to set/unset position fixed
The children (RichTextEditor component) would call the function (e.g. onRegisterPinableToolbar 😁) on componentDidMount with the node from ReactDOM.findDOMNode and a callback that the child can use to modify it's node style.
Notes:
Of course you would also need to to cleanup on componentWillUnmount.
Don't know much about your application but I would try to create a HOC for the Editor, e.g. PinableToolbarRichTextEditor
By abstracting the register to scroll events to a service you can optimize using requestAnimationFrame, and provide fallbacks for older browsers.
The function passed to the children would look something like this (node:Node, setPinability:Function) => unregister:Function
I know the naming pinability is not the best 😶
Instead of trying to get a ref to a deeply nested component, pass down the 'fixed' state as a prop, and let the great-great-(great?)-grandchild check the property and set its own style.
I am developing my client-side app with YUI3's APP Framework. I am having the following problem: I want to be able to have a few views (let's call them widgets) that are going to stay in the same place on page but under App's container Node, so that events can be registered within App's logic. For example I want a left menu which will have dynamic content (user's navigation panel).
This can be done by creating the menu as a subview, but navigating to another page will result in a page transition and thus, the menu will be included in page transition. I want this subview to be a shared view within many other pages(where page is formed from multiple subviews) but excluded from app's navigation behavior and rendered only once(and updated via custom events).
Does anyone with more experience using YUI App Framework knows hot can I tackle this problem? Thanks.
Yes it can be done. After a closer look on YUI's APP Framework API I found that there are 2 separate properties: container and viewContainer. The former is the node in which the app will reside and the later one is used for dynamically changing the active view on the page. Having this 2 separate properties you have the power to add watever content you want in App besides the pages (which are going to change based on events && routes).
So to conclude you can have a div element which is going to be app's container. Within this element you can write whatever html you want. You can also have another View class here which is going to change based on events(and YUI's custom events are very powerfull). And besides all this "static" html you must have another div(or of course, another html element) which is going to be the active view's container(that'll change based on events or in majority of cases, based on page's URL).