ANTD table Print using ReactToPrint component - javascript

I am trying to print ANTD table using ReactToPrint hook, everything seems to work fine, but I want to show some text on top of page before print.
means I want to show some text for header purpose, when I am setting the visibility of header component true, its not print on first click, it shows on 2nd click, but I want to show the header on first click and when I print or cancel, header should be hide.
Please help me, Please hit print button two time to see the result in the below link.
https://codesandbox.io/s/usestate-not-updating-data-when-passing-from-parent-functional-component-using-r-forked-xuhnl
Thanks in Advance

When the handlePrint function is called, the ref componentRef points to the previous version of the component. printHeaderVisible only becomes true at the time of the next render.
You can try to postpone the print call until the next render like this
const reactToPrintFunc = useReactToPrint({
content: () => componentRef.current,
onBeforeGetContent: () => setprintHeaderVisible(true),
onAfterPrint: () => setprintHeaderVisible(false)
});
const handlePrint = () => {
setTimeout(reactToPrintFunc, 0);
};
or do as advised in this issue
const handlePrint = useReactToPrint({
content: () => componentRef.current,
onBeforeGetContent: () => {
return new Promise((resolve) => {
setprintHeaderVisible(true);
resolve();
});
},
onAfterPrint: () => setprintHeaderVisible(false)
});

Related

Bootstrap popover content callback called twice on every second click

I'm trying to create a feature that will display the popover with manual click event.
My goal is to populate the popover and display newest data through ajax call after every click.
The problem I'm facing is described on the title.
For example:
1st click -> call once
2nd click -> call twice
3rd click -> call once
4th click -> call twice
...
The code look like this:
$popoverButton.popover({
container: 'body',
template: `<div></div>`,
title: 'title',
content: function () {
console.log('*'); // this called twice on every second click
let id = $(this).attr('data-id');
return initPopover(id);
},
html: true,
trigger: 'manual',
});
function initPopover(id) {
let $popover = $('<div class="popover-body"></div>');
$popover.attr({'id': 'popover-body-' + id});
let $spinner = $(`<div class="spinner"><span class="spinner-border"></span></div>`);
$popover.append($spinner);
let $sellers = $('<div class="sellers"></div>');
$popover.append($sellers);
return $popover;
}
To open the popover, I declared the click event with these functions:
$popoverButton.on('click', function () {
closePopover();
openPopover($(this));
});
closePopover() {
$popoverButton.popover('hide');
}
openPopover($targetButton) {
// hide all opened popovers
$('.popover').popover('hide');
$targetButton.popover('show');
getSellersAndAppendData();
}
I'm not sure why this happened. Please help.

How to test if url is updated while keeping history.location.search with Jest

I have a react application where I want to test the folowing behaviour.
I have some search criteria in the url /?my_filter_value=%5B\"FR\"%5D, and I have a button, when I click the button, a modal shows up and the url is updated /some_modal_id?my_filter_value=%5B\"FR\"%5D.
The test scenario I have is: Given that I click the button > When the modal shows up > I expect the url to be updated accordingly ie. some_modal_id is added to the url while keeping the initial search criteria.
describe('Given I click on the button', () => {
act(() => {
buttonModale.find('#actualButton').at(1).props().onClick();
});
describe('When the modal shows up', () => {
const initialUrlWithSearchCriteria = "/?my_filter_value=%5B\"FR\"%5D";
const history = createMemoryHistory({
initialEntries: [initialUrlWithSearchCriteria],
initialIndex: 0,
});
//expect(history.location.search).toBe(initialUrlWithSearchCriteria );
act(() => {
mount(
<Router history={history}>
<MyModalComponent showModal={true}/>
</Router>
);
});
const expectedModalUrl = `/some_modal_id`;
test('I expect the url to be updated with the modal id and keep the applied search', () => {
expect(history.location.pathname).toBe(expectedModalUrl);
expect(history.location.search).toBe(initialUrlWithSearchCriteria);
});
});
});
The first expect clause test is passing, so the url is actually getting "some_modal_id" part, but the second expect clause is failing. It seems that history.location.search is always an empty string.
I have tried to test if history.location.search is actually taking the initial value I am giving it and it seems to be working and the commented out expect case was passing.
Any help or tip on this will be highly appreciated!

Remove hover effects when scrolling

I have been working on an application. There are multiple components on the page. The content inside them is scrollable. The expected functionality is when I scroll inside the component the hover effects on different elements should be disabled. After searching in the internet I have a working solution. I have created a HoverDisabler component like this,
import React, {useEffect} from 'react';
export const HoverDisabler = ({children}) => {
let timer = 0;
useEffect(() => {
document.addEventListener('scroll', () => {
clearTimeout(timer);
if(!document.body.classList.contains('hoverDisabled')){
document.body.classList.add('hoverDisabled');
}
timer = setTimeout(() => {
document.body.classList.remove('hoverDisabled');
},500);
}, true);
}, []);
return children;
}
The css for hoverDisabled is as follows,
.hoverDisabled {
pointer-events: 'none',
}
And I am wrapping my root App component with HoverDisabler like this,
<HoverDisabler><App /></HoverDisabler>
Now in all the component, if I start scrolling the hoverDisabled class is added in the body and it gets removed when I stop scrolling. Everything is working perfectly. I am curious if this is the correct approach of having this functionality? Is there any shortcomings of this approach or some problem I am overlooking because of my lack of experience?
Since scroll event is an expensive event you can add a debounce on your scroll event like this:
function debounce(method, delay) {
clearTimeout(method._tId);
method._tId= setTimeout(function(){
method();
}, delay);
}
function scrollFunction(){
clearTimeout(timer);
if(!document.body.classList.contains('hoverDisabled')){
document.body.classList.add('hoverDisabled');
}
timer = setTimeout(() => {
document.body.classList.remove('hoverDisabled');
},500);
}
document.addEventListener('scroll', function() {
debounce(scrollFunction, 100);
});
This will surely optimize your code, as it will only fire scroll function lesser number of times. Even though there may be other approaches to the problem you're trying to solve I'm just suggesting a way to optimize your current code.

How to trigger load event listener in useEffect everytime component rerenders?

I'm trying to convert some static html/css site to react.js. In script tag there is this function that applies some css transition when the window loads everytime. Here's the function below:
window.addEventListener('load', function() {
document.querySelectorAll('.progress-custom-bar-fill').forEach(e => {
e.style.width = `${e.getAttribute('fill-progress')}%`;
})
})
<div
className={`progress-custom-bar-fill ${goodOrOk}`}
fill-progress={progress}
/>
I tried appyling style property directly to the div like this:
<div
style={{ width: `${progress}%` }}
className={`progress-custom-bar-fill ${goodOrOk}`}
fill-progress={progress}
/>
It worked, but it doesn't appy css transiton
I tried useEffect, it works only first time when the window loads, but when switching between pages it doesn't work. This is what I tried:
useEffect(() => {
function updateProgressBar() {
document.querySelectorAll('.progress-custom-bar-fill').forEach((e) => {
e.style.width = `${e.getAttribute('fill-progress')}%`;
});
}
window.addEventListener('load', updateProgressBar);
return () => window.removeEventListener('load', updateProgressBar);
});
How to make useEffect to rerender on load event? Or is there any other solution for this? Thanks in advance

React componentDidMount not called on component reload

I have a list of data table. In data table I have data w.r.t to some device Whenever I click ID I open a sidebar with some data displaying inside that.
The problem what I am facing is onclick of ID first time it calls the api gets the data and displays properly. But, after closing sidebar when I click again on ID it doesn't load anything (no calls for APIs).
I am not able to create code pen for that but below is my code.
My Code -
onCLick ID -
_onClickCompliance(deviceId);
const _onClickCompliance = deviceId => {
ReactDOM.render(
<ComplianceDetails deviceId={deviceId} />,
document.getElementById("ComplianceDetailsModalDiv")
);
};
Inside ComplianceDetails component - First time onClick it goes inside componentDidMount but on click again it's not. That's why I have componentDidUpdate for this. If I remove this componentDidUpdate, it always loads the old data in sidebar after onCLick of ID in table.
`getDetailsByDeviceID` this is called to get the data from API and sets value in state
My Code -
componentWillReceiveProps() {
this.setState({ sideBarShow: true });
}
componentDidMount = () => {
this.getDetailsByDeviceID();
};
componentDidUpdate(prevProps) {
if (this.props.deviceId !== prevProps.deviceId) {
this.getDetailsByDeviceID();
}
}
getDetailsByDeviceID code -
getDetailsByDeviceID = () => {
try {
this._getComplianceDetailsApi(); //apis
} catch (err) {
toast({
message: err,
flavor: "error",
options: { isHtml: true }
});
}
};
If I remove this it calls the page indefinitely.
if (this.props.deviceId !== prevProps.deviceId)
Do I have to call componentWillUnmount()? Please guide me.
Let me know If I am not clear. Thanks.
If you want your component to re-mount when deviceId change you can use the key prop on ComplianceDetails, like this :
<ComplianceDetails key={deviceId} deviceId={deviceId} />

Categories