What I want to do is to make a nice message box that appears when I'm saving something, I have access to a state that tells me if it's loading or not, but I can't seem to make a component that always appears, no matter how much you've scrolled.
The page is pretty long so wherever they click on a button that triggers this save function, I want this to appear. Where they are.
I've used Semantic UI in this project, and I've tried their sticky component but it only makes the component follow the screen like 50px, I want that number to be infinite.
Thankful for every answer
You could also achieve this with a fixed modal I guess.
Inside your main component:
state = {
// (...)
isLoading: false
}
// (...)
render() {
return (
// Rest of your code
{this.state.isLoading && <MessageComponent/>} // or however you're rendering the message/modal
// Rest of your code
)
}
Then in your respective css file styling your MessageComponent:
.messageComponent {
position: fixed;
}
Related
First of all, a shout out to Yoav the developer of React Uploady. It's a very helpful library with all kinds of great fancy features (chunked uploads, upload progress hooks, etc).
I have a question about using the asUploadButton hook. Here's my use case: within my app, a user can choose from several places to upload a batch to. This is done by selecting a global dropdown that specifies the upload destination. Since user error is a real thing, I need to show them a confirmation screen. This is easy to do the first time they hit the "upload" screen: a state variable keeps track of whether they have confirmed they're in the right place, conditionally rendering either the confirmation component (if they haven't confirmed), or the Uploady component (custom UploadButton) if they have confirmed.
But the requirement is that we show the confirmation every time. Once a user has uploaded a batch, they should still be shown the confirmation if they click on that custom UploadButton again. I tried passing an onClick into the asUploadButton component, but that callback is actually called after showFileUpload - and I want to show an interstitial modal once the button is clicked but before showFileUpload is called. Is there any hook to call a method before showFileUpload? Or am I approaching this completely wrong? Advice of any kind is very appreciated.
as answered here on the react-uploady discussions page:
In your case, I think a custom button will make more sense. In the end, asUploadButton is a very simple component that mainly does one thing and that is, call showFileUpload available from the UploadyContext.
You could create your button component that implements the logic (show confirmation) and when user approves calls the showFileUpload.
You get access to the method using:
import { useUploady} from "#rpldy/uploady"
//...in your component:
const { showFileUpload } = useUploady();
const onClick = () => {
//custom logic
showFileUpload();
};
I have a button in my Header component. When it is clicked, it calls a toggleNav function stored in my context.js. This function changes the state of isNavOpen from false to true. The navgiation then opens. There is no CSS in my project that should allow this behavior. I also don't see any JS code that should allow this behavior either. Could someone tell me what code allows my navigation to open and close?
My codesandbox
This is down to the basic way that React works, when you change the state of a component, it re-renders itself with the new values you've set into state.
Specifically it's this bit of Header.js:
{context.state.isNavOpen && (
<div className="js-nav nav">
...
When the component renders the first time, context.state.isNavOpen is false, and false && anything is still false, so javascript ignores the code after the &&. That means it skips over the menu code.
The second time it renders, after you update the state which is pushed to context and then passed to <Header> as a prop (!), the component re-renders with your menu code.
If you use your browser's dev tools to inspect the DOM before and after you click the button, you'll find that the menu isn't hidden and shown, but rather when you don't see it, it's gone from the DOM altogether.
It's react feature whenever state changes component re-renders
same thing happening here
{context.state.isNavOpen && (
isNavOpen is toggling (true to false), (false to true)
for example - you can check it simply
class Toggle extends React.Component {
state = {
visibility: false
}
toggleVisibility=()=>{
this.setState(prev=>({visibility:!prev.visibility}))
}
render() {
const {visibility} = this.state;
return (
<div>
<button onClick={this.toggleVisibility}>Click Me</button>
<h3>{visibility?'Welcome':''}</h3>
</div>
);
}
};
On what scenario can i use intern's leadfoot waitForDeletedByXpath function? From the documentation, what I understood is this method waits for the element to become invisible in Page. But while implementing it doesn't seem so. The scenerio i'm using this is as follows:
There is a page in my application where i can search for data with some predefined arguments. After clicking on search button the loading icon appears on the page until the data is loaded in the datagrid and the loading icon disappears after the data is loaded . so I'm trying to use this function to wait until the loading icon disappears from the page so that i can read the data in datagrid without having any issue but it doesn't seems to work that way.
Can someone please throw some light on how this function works and point me towards the right direction to achieve what i'm trying to do.
thanks
I believe what's happening here is a slight misinterpretation of what the waitForDeletedByXPath method does.
What the documentation for this method says is:
"Waits for all elements inside this element matching the given name attribute to be destroyed."
When your loading icon disappears it is most likely still part of the DOM, albeit it is just set to invisible. This method expects the element to no longer be part of the DOM at all.
What you need to do, from my experience, is set up your own "wait for element to be invisible" method for your loading icon.
For example:
return this.remote
.then(function () {
const waitForLoadingIconNotDisplayed = function (remoteSession) {
return remoteSession
.findByCssSelector('your_loading_icon_css_selector')
.isDisplayed()
.then(function (isDisplayed) {
if (isDisplayed) {
return waitForLoadingIconNotDisplayed(remoteSession);
}
return true;
});
};
return Promise.all([waitForLoadingIconNotDisplayed(this.parent)]);
})
This will loop until the condition is met that your loading icon is no longer set as displayed in the UI using the Promise.all() call.
Hope this helps steer you along the right path!
Suppose I have two screens:
Screen A
Screen B
I am initially landed on Screen A. When I click on a Button I navigate to Screen B. When I press Back Button, I am again navigated to Screen A.
I want to call an action creator when I am navigated to Screen A as mentioned in above scenario.
I just want to know that which lifecycle event will be called every time when a screen is presented.
Isn't there some event like componentWillAppear()?
Note: I am using react-native with react-navigation for navigation.
This can now be done with plain react navigation via their listeners:
In your Component A:
componentDidMount = () => {
this._componentFocused();
this._sub = this.props.navigation.addListener(
'didFocus',
this._componentFocused
);
}
componentWillUnmount() {
this._sub.remove();
}
_componentFocused = () => {
this.setState({dataToShow});
}
React Navigation docs - Lifecycle
When you navigate from one screen to another, the first screen will not be unmounted, but still on the stack, just hide in the background.
What you need might be componentDidFocus, but it's currently in design not avaiable yet, see react-native open issue #51.
You can try this alternative way: react-navigation-addons. With this you can have events focus & blur which may suit your needs.
If you use react-native-navigation, you can listen for appearance events: https://wix.github.io/react-native-navigation/#/screen-api?id=listen-to-visibility-events-globally
Every time you perform a render in React.js, the UI scrolls to the top of the page.
JSFiddle: http://jsfiddle.net/bengrunfeld/dcfy5xrd/
Any nifty or reactive way to stop that?
E.g. If a User scrolls down the page, then pushes a button which causes a Render, the UI would stay in the same scroll location as before.
// Forces a render which scrolls to top of page
this.setState({data: data});
UPDATE: Why does the UI scroll to the top for some renders, but not others?
Ok if anyone read this , in my case the problem wasn't any of above. You must try first suggestions on above any way. I did everything including preventDefault() but didn't help me. The problem was ; using styled-components. Because, styled-components give a random classname every render. So it resets scroll. I gave the class name from css and solved my problem.
#floydophone answered this one on Twitter.
https://twitter.com/floydophone/status/608129119025561600
#bengrunfeld #reactjs you forgot preventDefault() on your link handlers
Wanted to add here for those who are not using anchor tags, preventDefault will not save you. As bizarre as it is, for me it was related to rendering my child components inside a div with
display:table > display:tablecell
For some reason the child component's scroll position is lost in this situation when there is any re-render. Problem vanished when I switched to flexbox (display:flex).
If render trigger scrolling to the top it usually means some UI component is changing its dimension because of the state, this can be fixed by adding a minimum width/height
This could be happening because of the change in redux state, which will show the changes everywhere in the code where it is getting used. Try making the change using the local state of that component on action of which, the page is getting scrolled.
2022 Hacky Solution:
I couldn't find a way to completely prevent the scrolling on the re-render. preventDefault didn't help, and I didn't have access to the specific element structure, but I did have the className of the scrolling element.
useEffect(() => {
const el = document.getElementsByClassName('my-classname')?.[0];
const newTimeoutRef = setTimeout(() => el?.scrollTo(0, scrollTop), 50);
return () => clearTimeout(newTimeoutRef);
}, [scrollTop]);
Then you set the scrollTop (as a component state) inside the event that was previously causing the scroll to top.
The hack here is that setTimeout, which basically gives the DOM time to scroll to the top before calling your el.scrollTo, it flashes a bit, but it was the best solution that worked for me.