-
-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UpdatedDom ignored on onbeforeprint #140
Comments
Hello. Can you please show what |
It just sets a state property to true so that the rendering can react and
render the additional elements out too
Matthew Herbst <[email protected]> schrieb am Fr., 28. Juni 2019,
20:05:
… Hello. Can you please show what setPrintMode does?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#140>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AG4MXZ5FHCP4OSMYEW4QOFDP4ZHG5ANCNFSM4H4EAJ4A>
.
|
Hmm. |
Thank you. Well, in React I can imagine many cases when I need to "react" to "beforePrint" by setting states. So I think this might be an issue others are also running into. |
I'm trying to think if there is an elegant way to do this without using |
I see. My opinion is, that we should use new technologies if they fit us. Holding them back to support outdated browsers is just slowing down development at all (in fact also for npm-packages). If a solution wants to use reat-to-print, it might have polyfilled for IE anyways, as a client-application in most cases uses eg fetch, array-functions, ... . Pls keep me updated. But for the moment i guess I won´t be able to change anything on "onbeforeprint". Thought about it, but I didn´t came up with a use-case for "onbeforeprint", that would not resolve in a change in the state of a component (if I leave direct DOM-Manipulation out as it is not recommended in React) |
I'm very open to using promises and making people polyfill for support. Just will be a slightly longer process since it involves releasing a breaking change. Give me a couple of days to work on this - I do think it's needed, so thank you for the idea! |
So, the way I envision using this is that // This is the function you would pass to `onBeforePrint`
handleBeforePrint = () => {
return new Promise((resolve, reject) => {
this.setState(newState, resolve);
});
} Does that seem ok to you? |
@gregnb do you have any objection to anything in this thread? |
might work out. One has to try if the rendering is already done too, when the setState calls the callback function. My current situation is based on hooks. As I know hooks don´t have such a callback option. Do you have any suggestion in that case too? |
Hmm. I would image then that you would have to save a reference to the So, in a class world: // This is the function you would pass to `onBeforePrint`
handleBeforePrint = () => {
return new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
this.setState(newState);
});
}
componentDidCatch(error) {
// You would likely want to check that the update was for the `setState` you called versus just a prop change or something
this.reject();
}
componentDidUpdate() {
// You would likely want to check that the update was for the `setState` you called versus just a prop change or something. Could do that by setting a special key in state or something
this.resolve();
} Functional could work in a somewhat similar manner. (This is a quick example that I thought about that I think will work, and likely could be improved.) const Component = (props) => {
const [state, setState] = useState({ printMode: false });
// We could talk about allowing `onAfterPrint` to handle Promises as well but I don't think there is a use case for that right now?
const handleAfterPrint = useCallback(
() => {
const { resolve, reject, ...rest } = state;
setState({ ...rest, printMode: false });
},
[state] // Micro-optimization, the `useCallback` likely isn't needed
);
const handleBeforePrint = useCallback(
() => {
return new Promise((resolve, reject) => {
setState({ ...state, printMode: true, resolve, reject })
});
},
[state] // Micro-optimization, the `useCallback` likely isn't needed
);
// Runs _after_ the render has been completed
useEffect(
() => {
const { resolve, reject, ...rest } = state;
// Not sure if you would ever need to call `reject` since I don't think `setState` calls can fail?
if (state.printMode && resolve) {
resolve();
setState(rest);
}
},
[state]
)
return (
<ReactToPrint
...
onAfterPrint={handleAfterPrint}
onBeforePrint={handleBeforePrint}
/>
);
} What do you think about that? Thanks again for the discussion on this, very interesting to work through! |
Hmm. Looks quite complicated and error prone. I don´t have much time to try out too. Currently I am thinking about a React-context could help us out. I don´t know if this is async too. |
If you can think of a better solution please let me know. The issue is two fold: the parent has to resolve/reject the promise, and only the parent knows when it is done re-rendering. |
I have the same issue, I want to render only when print clicked,
|
@michael-ecb it sometimes works because there is a race condition happening, so sometimes your render will beat it and sometimes it won't. What are your thoughts on what I've suggested for how it could be done above? |
@MatthewHerbst sounds greater than use React-context ... |
We could look into using context, though it would likely require us to raise our minimum required React version, which I think is a downside compared to asking people to provide a Promise polyfill since most probably already do that if they support IE and such. |
Hmm. |
Interesting, I didn't know about the API before. Can you maybe write a pseudo-code example of how you think that would work? From the docs I don't see any way of the observer telling you that the mutation is done, rather, you have to tell it that the mutation is done. We could pass a function from props down into the callback, but that would require users of the library to have intimate knowledge of how |
Well, it tells you if something in DOM changed. Basically you create an observer-object which includes the callback. and thell it to observe a dom-element with given extra-config-parameters. (plain js as here: https://medium.com/@abbeal/listening-to-the-dom-changes-with-mutationobserver-b53a068a58d2) You can even use a existing react-component like I thought of something like this: However, mutationobserver is IE11 and above. and also, it might also not work in our case as i think of it. As it would recognize changes, but it would trigger after the first change (which might not be enough) and would never trigger when react doesn´t update the DOM at all. |
I think there are only 2 ways:
Hmm, second way has the same drawback like MutationObserver in terms of reacting on the very first rerendering, however, this might be enough at all. Additionally, second method uses already-built-in react-features, doesn't need a promise and is quite easy to use for users. (as they would only need to wrap their render-function into a tag. |
Ok, react-to-print doesn´t use a children-prop. Don´t know where i got that from. However, Context-method would work also, altough a bit less easy Sorry for that much text. I will be able to come up with some code-examples when i work again on that part of my project which uses react-to-print. But that will be in ~ 3 weeks i guess as i am on holiday. Currently I just can share my thoughts. |
I personally think the simplest solution is for The proposal you've suggested with waiting for
|
This has been addressed in #146, published as v2.2.0 which adds support for |
Hi, I am using this lines
where i am setting Printmode to true, in order to render additional Content (Legend) for the print.
However. It is called and the DOM updated (as i can see in the background, but in the print window it still shows the "non-print-version".
the full thing I use:
The text was updated successfully, but these errors were encountered: