Skip to content
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

HostedForm is not showing up #5

Open
dexterjohncaones opened this issue Mar 29, 2023 · 17 comments · May be fixed by #12
Open

HostedForm is not showing up #5

dexterjohncaones opened this issue Mar 29, 2023 · 17 comments · May be fixed by #12

Comments

@dexterjohncaones
Copy link

I have observed that when the HostedForm is properly working, you should see the code existing inside the body of the page when you inspect its element. In our system, we are using react with material UI and placing the HostedForm inside the material Drawer, When I close the drawer and re-open it, the on-click function of the HostedForm form does not work anymore. It seems like the functionality that adds the class="show" to the element that makes the form appear is not working.

@brendanbond
Copy link
Owner

brendanbond commented Mar 30, 2023

I'm not sure I understand the specific issue enough to help, perhaps you can provide a minimal, reproducible example?

@dexterjohncaones
Copy link
Author

dexterjohncaones commented Mar 31, 2023

I'm not sure I understand the specific issue enough to help, perhaps you can provide a minimal, reproducible example?

@brendanbond Here's the code sample. Thank you.
https://codesandbox.io/s/inspiring-thunder-ock17k?file=/src/App.js
AcceptUI

@dexterjohncaones
Copy link
Author

dexterjohncaones commented Apr 4, 2023

@brendanbond Sometimes the library doesn't load properly. It shows an error
image

@brendanbond
Copy link
Owner

<HostedForm /> is just a React wrapper for this library. Both the error you describe and the behavior you're seeing, as you indicated, is something in the show/hide code in the library itself provided by Authorize.net. The solution might be to find the fix and host your forked version locally, but I won't have time to look more deeply as this library just aims to wrap it in idiomatic-ish React.

@brendanbond
Copy link
Owner

Whoops, I pressed close accidentally! I'd like to leave this open in case you come to a solution in the library code, please post it if you do!

@brendanbond brendanbond reopened this Apr 8, 2023
@pandas9
Copy link

pandas9 commented Sep 28, 2023

Had the same issue fixed by copying code from the git repository and creating a custom component

Due to the nature of react.js script sometimes won't load properly or it will load twice if any of that happens authorize net won't show the popup

@pandas9
Copy link

pandas9 commented Sep 28, 2023

Wrapper would be much better alternative to load the script same as stripe does it and then having to put payment button inside wrapper

@brendanbond
Copy link
Owner

brendanbond commented Sep 28, 2023

Wrapper would be much better alternative to load the script same as stripe does it and then having to put payment button inside wrapper

Thanks, @pandas9 although I'm not sure I follow. The script is loaded via this hook - can you elaborate on how Stripe does something similar? FWIW, these components/hooks act as a fairly thin wrapper around the AcceptJS library, which is structured far differently from Stripe's (really excellent) React provider libraries.

The truth is, I've moved on from the project that I wrote this for (although, to my knowledge, that project still uses this library in production). I would welcome a PR if you have time to try and tackle the issue you're running into. Otherwise, I'll need some more context or concrete steps to reproduce any trouble you're having. Thanks!

@pstatxde
Copy link

pstatxde commented Mar 28, 2024

Wrapper would be much better alternative to load the script same as stripe does it and then having to put payment button inside wrapper

We are hitting the same issue with HostedForm as @pandas9. In our 4 step checkout process in which the user can navigate forward and backward through the steps, the first time through clicking the "Pay" button displays the lightbox with credit card fields properly. Once we navigate away from that screen, then back to it, the button no longer opens the lightbox.

The issue occurs when the underlying component that HostedForm is on is loaded, then unloaded, then reloaded. For example, if HostedForm is on the "Payment" component, this code will cause the issue since it loads and unloads the Payment component depending on the checkout step the user is on: { step === 3 && <Payment /> }

If I change the above code to simply hide the Payment component (as opposed to unloading it), the Pay button works correctly as the user navigates back and forth to the Payment component: <div className={step === 3 ? "d-block" : "d-none"}><Payment /></div>

@brendanbond
Copy link
Owner

@pstatxde if I'm understanding correctly, the solution is to make sure that react doesn't unmount remount and remount the component - shouldn't that be taken care of at the component's consumer level, rather than in the component itself, or is there something that should be done to ?

@obsoke
Copy link

obsoke commented Apr 3, 2024

I've been running into the same issue. The <HostedForm /> modal pops up the first time you click the button but if you navigate to a new page & back, it no longer opens.

As an experiment, I commented out the <HostedForm /> component from react-acceptjs and tried using AcceptUI.js + a <button className="AcceptJS"> by itself (as documented by authorize.net's docs). I can confirm that this seems to be an issue not with react-acceptjs but the AcceptUI.js library. It looks like even though the AcceptUI.js remains in the <head>, if the component with <HostedForm /> is unloaded/reloaded, the modal will not appear again.

My guess is that AcceptUI.js attaches an event listener to the button. Navigating away to another page within the SPA means the button is unmounted from the DOM & re-visiting your component with <HostedForm> does not re-attach the event listener. My guess is probably accurate as the AcceptJS docs contain this warning:

If you are building your page dynamically, be sure that your page loads the Accept JavaScript library after the button is defined. For the library to correctly interface with the button, the button must already exist in the DOM when the library is loaded.

The only solution I can think of would be a change to the useScript hook. Currently, there is a cachedScripts array that is used to prevent adding AcceptUI.js to the DOM multiple times. Instead, the solution might be to:

  1. Check if the DOM already contains a script[src=URL] tag.
  2. If it does, remove it.

The rest of the useEffect() hook in useScript() would proceed, adding AcceptUI.js to the DOM.

This is a bit hacky but without being able to modify AcceptUI.js directly, I'm not sure what other solutions there are. In a React SPA, it's expected that different components will unload / load into the DOM as the user navigates around the application. AcceptJS seems like an old library that was written for a pre-SPA world so special care might need to be taken to make it work properly with React.

If this solution is acceptable to @brendanbond, I'd be happy to open a merge request.

@brendanbond
Copy link
Owner

@obsoke

Check if the DOM already contains a script[src=URL] tag. If it does, remove it.

Hmm, it seems like from your very good description of the problem, <HostedForm /> (i.e. AcceptUI.js) is the only script that needs to be loaded after the button is instantiated in the DOM. Rather than modifying useScript, maybe that particular component could just load the script in a useEffect hook and then, on cleanup, remove it (we could even memoize the actual script content to avoid having to call to the network on mount and unmount). This way, the other two components are unaffected and <HostedForm /> (which funnily enough is so distinct from the others that I considered making two separate libraries) can ensure that its AcceptUI script is loaded after the button. Your thoughts?

If this solution is acceptable to @brendanbond, I'd be happy to open a merge request.

Feel free, that would be awesome!

@pstatxde
Copy link

pstatxde commented Apr 4, 2024

@brendanbond

@pstatxde if I'm understanding correctly, the solution is to make sure that react doesn't unmount remount and remount the component - shouldn't that be taken care of at the component's consumer level, rather than in the component itself, or is there something that should be done to ?

Sorry for the late reply. Your understanding is correct and my workaround was to ensure my component that HostedForm is on is hidden/unhidden rather than being unmounted/mounted in the DOM. That said, I think it's better if HostedForm works correctly when the underlying component is unmounted and remounted, since most apps likely work in that manner.

@pstatxde
Copy link

pstatxde commented Apr 4, 2024

@obsoke

In a React SPA, it's expected that different components will unload / load into the DOM as the user navigates around the application. AcceptJS seems like an old library that was written for a pre-SPA world so special care might need to be taken to make it work properly with React.

Agreed.

If this solution is acceptable to @brendanbond, I'd be happy to open a merge request.

This would be very helpful. Thank you as well.

@obsoke
Copy link

obsoke commented Apr 4, 2024

Rather than modifying useScript, maybe that particular component could just load the script in a useEffect hook and then, on cleanup, remove it (we could even memoize the actual script content to avoid having to call to the network on mount and unmount). This way, the other two components are unaffected and <HostedForm /> (which funnily enough is so distinct from the others that I considered making two separate libraries) can ensure that its AcceptUI script is loaded after the button. Your thoughts?

By 'that particular component', do you mean <HostedForm />? Would this mean <HostedForm /> would not use useScript after this change?

I do like the idea of memoizing the script content.

@brendanbond
Copy link
Owner

By 'that particular component', do you mean ? Would this mean would not use useScript after this change?

Yeah, it uses a separate script (AcceptUI.js) IIRC, so we can just ditch useScript for that one if that fits the bill for the fix.

@obsoke
Copy link

obsoke commented Apr 4, 2024

Sounds like a plan! I'll spend some time on this today & tomorrow, expect a PR shortly!

@obsoke obsoke linked a pull request Apr 4, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants