» npm install react-new-improved-window
Using react-window - is this good and performant code?
Open a component in new window on a click in react
reactjs - How to get the reference for new window object from a Component which opens the window? - Stack Overflow
react-window v2.0 is out 🥳
Is react-new-improved-window safe to use?
Is react-new-improved-window well maintained?
Videos
» npm install react-new-window
I am building an application that displays a very long list of data - think a Spotify-style playlist with 10,000+ rows, each with several columns and unique thumbnail images.
I've come across react-window to improve performance, as this only renders the rows in view rather than all 10k.
However, by default it doesn't support sticky rows, and what I want is a header, a sticky row, and then my list rows, all within a single scrolling container.
I started from their official demo, here.
I've now modified this to get it working the way I want.
But there's an awful lot of re-renders happening, and I'm not confident my code is performant.
Can this codesandbox be improved upon for better performance? And is this good code in general?
https://codesandbox.io/p/sandbox/react-window-with-sticky-headers-chp6dx
I've created a generic StickyList component, and my more specific MyList component that passes the content down to it.
Many thanks for any help!
EDIT:
Following advice in the comments, I've rewritten the demo using Tanstack Virtual. It seems clearer and easier to control and manage!
https://codesandbox.io/p/devbox/suspicious-wildflower-4prdcj?workspaceId=ws_4XrM7ka75TBJaLftpJJK6R
» npm install react-window
You can use ReactDOM.createPortal to render a component in a new window as David Gilbertson explains in his post:
class MyWindowPortal extends React.PureComponent { constructor(props) { super(props); // STEP 1: create a container <div> this.containerEl = document.createElement('div'); this.externalWindow = null; } render() { // STEP 2: append props.children to the container <div> that isn't mounted anywhere yet return ReactDOM.createPortal(this.props.children, this.containerEl); } componentDidMount() { // STEP 3: open a new browser window and store a reference to it this.externalWindow = window.open('', '', 'width=600,height=400,left=200,top=200'); // STEP 4: append the container <div> (that has props.children appended to it) to the body of the new window this.externalWindow.document.body.appendChild(this.containerEl); } componentWillUnmount() { // STEP 5: This will fire when this.state.showWindowPortal in the parent component becomes false // So we tidy up by closing the window this.externalWindow.close(); } }
The upvoted answer works great!
Just leaving a function component version here in case people are searching for that in the future.
const RenderInWindow = (props) => {
const [container, setContainer] = useState(null);
const newWindow = useRef(null);
useEffect(() => {
// Create container element on client-side
setContainer(document.createElement("div"));
}, []);
useEffect(() => {
// When container is ready
if (container) {
// Create window
newWindow.current = window.open(
"",
"",
"width=600,height=400,left=200,top=200"
);
// Append container
newWindow.current.document.body.appendChild(container);
// Save reference to window for cleanup
const curWindow = newWindow.current;
// Return cleanup function
return () => curWindow.close();
}
}, [container]);
return container && createPortal(props.children, container);
};
I was trying to do something similar but wanted the popup window to print when it opened.
Here's the solution (using React hooks):
import React, {useEffect, useRef} from 'react';
import NewWindow from "react-new-window";
const PopupWindow = () => {
const thisWindow = useRef(null);
// This will fire when thisWindow reference changes.
useEffect(() => {
thisWindow.current.window.focus();
// thisWindow.current.window.print(); // To print when the popup window loads.
}, [thisWindow]);
return (
<>
<NewWindow
ref={thisWindow}
>
<p>
Your content here
</p>
</NewWindow>
</>
)
}
export default PopupWindow;
We can access window object created in the component by using const chartWindow = useRef(null) on the component and access like this way, chartWindow.current.window.focus()
» npm install @asutrick/react-new-window
Just a quick note that version 2 has been published.
Docs and examples can be found at https://react-window.vercel.app/
High level overview of what changed and why you might want to upgrade is in the change log but I'll save you a click:
-
More ergonomic props API
-
Automatic memoization of row/cell renderers and props/context
-
Automatically sizing for
ListandGrid(no more need forAutoSizer) -
Native TypeScript support (no more need for u/types
/react-window) -
Smaller bundle size
I appreciate the feedback that was shared during the alpha phase. If anyone has troubles with v2, please tag me here or on GitHub and I'll be happy to take a look.
Thanks!