Is it possible to utilize a Next.js image for triggering a form submission via onClick for Google OAuth?

Disclaimer: Novice User

I have successfully created a custom signin page with email and social media authentication using Next.js.

Now I would like to customize the styling by incorporating Next.js/Image to replace the submit button with a clickable icon or image that triggers the same action.

Below is the code for my fully functional signin page...

import React from 'react'
import {getProviders, signIn} from 'next-auth/react'
import { getCsrfToken } from "next-auth/react"
import styles from '../../styles/signin.module.css'
import Logo from '../../components/Logo'

export default function SignIn ({ csrfToken, providers }) {
  return (
    <div className={styles.content}>
      <div className={styles.cardWrapper}>
        <Logo className={styles.logo}/>
        <div className={styles.cardContent}>
          <form method="post" action="/api/auth/signin/email">
            <input name="csrfToken" type="hidden" defaultValue={csrfToken} />
            <input type="email" id="email" name="email" placeholder='Email..' />
            <button className={styles.primaryBtn} type="submit">Sign in with Email</button>
          </form>
          <p className={styles.seperator}> Or  </p>
          <form method="post" action="/api/auth/signin/google">
            <input name="csrfToken" type="hidden" defaultValue={csrfToken} />
            <button className={styles.primaryBtn} type="submit">Sign in with Google</button>
          </form>
        </div>
      </div>
    </div>
  )
}
export async function getServerSideProps(context) {
  const csrfToken = await getCsrfToken(context)
  const providers = await getProviders(context)
  return {
    props: { csrfToken, providers },
  }
}

The Next.js/Image code implementation would resemble this...

<a>
    <Image 
        priority="true"
        src="/google_login.png"
        alt="Google Login"
        width="200px"
        height="200px"
        layout="intrinsic"
     />
</a>

UPDATE:

In a previous iteration, I used a .map method to display provider buttons as shown below...

{Object.values(providers).map((provider) => {
    console.log(providers)
    if (provider.name === "Email") {
      return
    }
    return (
      <div key={provider.name}>
        <button onClick={() => signIn(provider.id)}>
          Sign in with {provider.name}
        </button>
      </div>
    )
   })}

Both methods are functional. How can I replace the button with an image instead?

Any suggestions or ideas are welcome.

Thank you in advance

Answer №1

Here is my approach to tackling this issue...

"/pages/auth/signin.js"

import React from "react";
import { getProviders, signIn } from "next-auth/react";
import { getCsrfToken } from "next-auth/react";
import styles from "../../styles/signin.module.css";
import Logo from "../../components/Logo";
import { GoogleLogin } from "../../components/GoogleLogin";
import { FacebookLogin } from "../../components/FacebookLogin";
import { TwitterLogin } from "../../components/TwitterLogin";

export default function SignIn({ csrfToken, providers }) {
  console.log(providers.google.signinUrl);
  return (
    <div className={styles.content}>
      <div className={styles.cardWrapper}>
        <Logo className={styles.logo} />
        <div className={styles.cardContent}>
          <form method="post" action="/api/auth/signin/email">
            <input name="csrfToken" type="hidden" defaultValue={csrfToken} />
            <input type="email" id="email" name="email" placeholder="Email.." />
            <button className={styles.primaryBtn} type="submit">
              Sign in with Email
            </button>
          </form>
          <p className={styles.seperator}> Or </p>

          {Object.values(providers).map((provider) => {
            if (provider.name === "Email") {
              return;
            }
            if (provider.name === "Google") {
              console.log(provider);
              return <GoogleLogin data={provider} />;
            }
            {
            if (provider.name === "Twitter") {
              console.log(provider)
              return (
                <TwitterLogin key={provider.id}/>
              )
            }
            if (provider.name === "Facebook") {
              console.log(provider)
              return (
                <FacebookLogin key={provider.id}/>
              )
            }
            }
          })}
        </div>
      </div>
    </div>
  );
}
export async function getServerSideProps(context) {
  const csrfToken = await getCsrfToken(context);
  const providers = await getProviders(context);
  return {
    props: { csrfToken, providers },
  };
}

the code snippet demonstrates the implementation of the GoogleLogin component (twitter and facebook have a similar structure)...

"/components/GoogleLogin.js"

import Image from "next/image";
import React from "react";
import { signIn } from "next-auth/react";
import styles from "../styles/signin.module.css";

export function GoogleLogin({ data }) {
  console.log(data);
  return (
    <a className={styles.googleLogin} onClick={() => signIn(data.id)}>
      <Image
        priority="true"
        src="/google_login.png"
        alt="Google login"
        width="40px"
        height="40px"
        layout="intrinsic"
      />
    </a>
  );
}

Upon clicking on the provider logos, they now correctly redirect to the respective OAuth pages.

Answer №2

Here is my proposed solution:

{Object.values(services).forEach((service) => {
    console.log(services)
    if (service.type === "Social Media") {
      return
    }
    return (
      <div key={service.type}>
        <button onClick={() => connect(service.id)}>
          <Image
            priority="true"
            src={service.src}
            alt={service.alt}
            width="60px"
            height="60px"
            layout="intrinsic"
      />
        </button>
      </div>
    )
   })}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to directly utilize functions from an imported JavaScript library, such as Change Case, within the template of a Vue component?

After successfully importing and using the Change Case library within the <script></script> element of a Vue component, I now seek to directly utilize the Change Case functions in the template itself. As of now, my understanding is that when d ...

Implementing AngularJS html5mode alongside nodeJS and Express

Currently, my AngularJS application is being served by a nodeJS server with Express. Everything runs smoothly when using the default angularJS routes (hashbangs); however, I am now attempting to enable html5 mode. To activate html5mode, I have implemented ...

Utilizing Vue's dynamic component feature to create event listeners

Issue: My current project involves creating a versatile table component that can be utilized by other components to display tabular data. Each cell in this table could contain one of three possible values: Text HTML Component While I have successfully im ...

What are the steps to designing a unique JSON data format?

When working with a JSON data structure containing 100 objects, the output will resemble the following: [{ "Value": "Sens1_001", "Parent": Null, "Child": { "Value": "Sens2_068", "Parent":"Sens1_001", "Child" : { ...

What is the process for enabling audio to start downloading immediately after the user clicks a button on the same webpage?

Can you please set up a function so that when users click on the "Download" button, the audio file automatically downloads? Product Details This beat is a melodic, bouncy, and hard track inspired by Lil Mosey. It is priced between $15-$75, with a master ...

What is the best way to implement smooth scrolling to an anchor tag from a different page in NextJS?

In my NextJS project, I have two main pages - the Home page and the Leaderboard page. The navigation bar code looks like this: <div className={styles.navItem}> <Link href="/"> <a className={styles.navLinks} onClic ...

Retrieve an array from a JSON object by accessing the corresponding key/value pair using the utility library underscore

I have a dataset in JSON format (as shown below) and I am attempting to use the _.where method to extract specific values from within the dataset. JSON File "data": [{ "singles_ranking": [116], "matches_lost": ["90"], "singles_high_rank": [79 ...

Variation in Map Behavior in d3 Due to Datum-Data Discrepancy

I'm relatively new to utilizing d3js and I am endeavoring to grasp the distinction between employing data and datum for associating data with elements. Despite having spent quite some time reading various materials online, I still lack an instinctive ...

Creating unit tests for linked functions in Node.js using Jest

Hey there! I'm looking to test a function using Jest that involves token verification and requires 3 parameters. Here's the code for the function: const verifyToken = (req, res, next) => { // Checking for token in header or URL parameter ...

Error message: Typescript and Styled-Component conflict: GlobalStylesProps does not share any properties with type { theme?: DefaultTheme | undefined; }

I've encountered an issue while passing props inside GlobalStyles in the preview.js file of my storybook. The props successfully remove the background from the default theme, but I'm receiving an error from Typescript: The error message states " ...

What is the correct way to apply a concatenated element id when using the .click() function in

Having an issue with assigning buttons to input boxes in a loop. When using concatenated element IDs with the .click() method, the buttons won't click for some reason. The following code works: document.getElementById("streamInput1") .addEventLi ...

Can someone provide a functional example of the recently introduced Next JS app folder Layouts RFC?

Exploring a groundbreaking method for organizing pages within the in-app folder in Next JS. However, despite reading about it, I am unable to locate any examples. Check out the Layout RFC Blogpost Could it be that this feature is still not accessible? ...

Display a placeholder page during the processing of an asynchronous task by Express JS

Perhaps this issue is either too simple to be overlooked or too complex to tackle, but despite my efforts of over 3 hours searching for a solution, I am unable to find one. It seems like it should be a common problem and I am just too inexperienced to loca ...

Unexpected addition of values to a list occurs when scrolling through a web element using Selenium

Having recently delved into Python, as well as programming in general, I am eager to extract data from a webelement that updates dynamically with scrolling using Selenium. A particular post on Stack Overflow titled Trying to use Python and Selenium to scro ...

Having all elements at the same height

I am looking to enhance my JavaScript code to only impact 4 items at a time. The goal is to target the first 4 instances of .prodbox, adjust their height accordingly, then move on to the next set of 4 and repeat the process. This sequential adjustment will ...

Custom HTML select element not triggering the onchange event

I found a code snippet on https://www.w3schools.com/howto/tryit.asp?filename=tryhow_custom_select that demonstrates a custom select input with an onchange event. However, I am facing an issue where the onchange event does not get triggered when I change th ...

Unusual marking on the navigation bar

Currently, I am making updates to a website that was created by a previous employee long before I joined the team. One of the requested changes is to eliminate the orange box surrounding the navigation links. The navigation appears to be generated using Ja ...

Having trouble understanding why adding raw HTML is yielding different results compared to generating HTML using jQuery

I need assistance with two jsFiddles: http://jsfiddle.net/kRyhw/3/ http://jsfiddle.net/kBMSa/1/ In the first jsFiddle, there is code that adds HTML to my ul element, including an 'X' icon in SVG format. Attempting to recreate this functionali ...

When a visitor accesses a webpage, enable port listening with Node.js and Express

Struggling to navigate the world of node.js, express, and port listening. My code is functioning properly, but only if I manually enter 'node index.js' in terminal to listen on port 3000... After hours of searching for a solution, my head is spi ...

Having trouble retrieving the value of an object and implementing a constant and static variable within a class

I have come across the following code: 'use strict'; const Request = require('request'); class CryptoKetHandlers { static async coins(ctx) { try { var CONTENT_TYPE = 'application/json'; ...