Home > Net >  React: pass ref to sibling component Function component
React: pass ref to sibling component Function component

Time:10-27

First this is my parent component :

import React from 'react'
import logo from '../Assets/LOGO.png'
import EmailInput from '../Components/LoginPage/EmailInput'
import PasswordInput from '../Components/LoginPage/PasswordInput'
import Rememberme from '../Components/LoginPage/Rememberme'
import SigninInput from '../Components/LoginPage/SigninInput'

import '../Styles/Login/login.css'
function Login() {
  return (
    <main>
      <div className='top'>
        <img src={logo} alt='Netflix' />
      </div>
      <section>
        <div className='si-card'>
          <h2>Sign In</h2>
          <EmailInput />
          <PasswordInput />
          <SigninInput />
          <Rememberme />
        </div>
      </section>
    </main>
  )
}

export default Login

PasswordInput:

import React from 'react'

function PasswordInput() {
  const passwordRef = React.useRef()
  function passwordValidation() {
    let value = passwordRef.current.value
    if (value.length <= 6) {
      console.log('Password must be smaller than 4 charectar')
    }
  }
  return (
    <div className='input-co'>
      <input
        type='password'
        id='password'
        placeholder=' '
        onChange={passwordValidation}
        ref={passwordRef}
      />
      <label htmlFor='password'>Password</label>
    </div>
  )
}

export default PasswordInput

EmailInput:


import React from 'react'

function EmailInput() {
  const reg = /^\w ([\\.-]?\w )*@\w ([\\.-]?\w )*(\.\w{2,3}) $/
  const emailRef = React.useRef()

  function emailValidation() {
    let value = emailRef.current.value
    if (!reg.test(value)) {
      console.log('Enter a valid email')
    }
  }
  return (
    <div className='input-co'>
      <input
        type='email'
        id='email'
        placeholder=' '
        onChange={emailValidation}
        ref={emailRef}
      />
      <label htmlFor='email'>Email or phone number</label>
    </div>
  )
}

export default EmailInput

SigninInput:

import React from 'react'

function SigninInput() {
  return <button className='signin'>Sign in</button>
}

export default SigninInput

How can I pass ref from EmailInput and passwordInput to SigninInput?

I want access to a value of two input when user is clicked on sign in button

CodePudding user response:

The usual flow of React is passing values as props down to children. You can't directly pass anything between siblings. You can, however, control the state in the parent component or a parent context and, from there, send the data down as props to the component that requires them.

I would structure your app using Login as a parent that handles the values for EmailInput and PasswordInput as state.

Login:

function Login() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  function handleEmailChange(value) {
    setEmail(value);
  }

  function handlePasswordChange(value) {
    setPassword(value);
  }

  function handleSignIn() {
    // use the values here
  }

  return (
    <main>
      <div className="top">
        <img src={logo} alt="Netflix" />
      </div>
      <section>
        <div className="si-card">
          <h2>Sign In</h2>
          <EmailInput onChange={handleEmailChange} />
          <PasswordInput onChange={handlePasswordChange} />
          <button className="signin" onClick={handleSignIn}>
            Sign in
          </button>
          <Rememberme />
        </div>
      </section>
    </main>
  )
}

PasswordInput:

function PasswordInput({ onChange }) {
  const passwordRef = React.useRef()
  function passwordValidation() {
    let value = passwordRef.current.value
    if (value.length <= 6) {
      console.log("Password must be smaller than 4 charectar")
    }
    onChange(value)
  }
  return (
    <div className="input-co">
      <input type="password" id="password" placeholder=" " onChange={passwordValidation} ref={passwordRef} />
      <label htmlFor="password">Password</label>
    </div>
  )
}

export default PasswordInput

EmailInput:

function EmailInput({ onChange }) {
  const reg = /^\w ([\\.-]?\w )*@\w ([\\.-]?\w )*(\.\w{2,3}) $/
  const emailRef = React.useRef()

  function emailValidation() {
    let value = emailRef.current.value
    if (!reg.test(value)) {
      console.log("Enter a valid email")
    }
    onChange(value)
  }
  return (
    <div className="input-co">
      <input type="email" id="email" placeholder=" " onChange={emailValidation} ref={emailRef} />
      <label htmlFor="email">Email or phone number</label>
    </div>
  )
}

export default EmailInput

CodePudding user response:

  1. It would be better to use state than use template refs to get the inputs values.
  2. In this case, you need to store your inputs state in the parent component and pass them as props to the child components.
import React from 'react'
import logo from '../Assets/LOGO.png'
import EmailInput from '../Components/LoginPage/EmailInput'
import PasswordInput from '../Components/LoginPage/PasswordInput'
import Rememberme from '../Components/LoginPage/Rememberme'
import SigninInput from '../Components/LoginPage/SigninInput'

import '../Styles/Login/login.css'
function Login() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = () => {
    console.log('email: '   email);
    console.log('password: '   password);
  }
  return (
    <main>
      <div className='top'>
        <img src={logo} alt='Netflix' />
      </div>
      <section>
        <div className='si-card'>
          <h2>Sign In</h2>
          <EmailInput email={email} setEmail={setEmail} />
          <PasswordInput password={password} setPassword={setPassword} />
          <SigninInput handleSubmit={handleSubmit} />
          <Rememberme />
        </div>
      </section>
    </main>
  )
}

export default Login

PasswordInput:


import React from 'react'

function PasswordInput({ password, setPassword }) {
  function passwordValidation(e) {
    const value = e.target.value
    setPassword(value)
    if (value.length <= 6) {
      console.log('Password must be smaller than 4 charectar')
    }
  }
  return (
    <div className='input-co'>
      <input
        type='password'
        id='password'
        placeholder=''
        value={password}
        onChange={passwordValidation}
      />
      <label htmlFor='password'>Password</label>
    </div>
  )
}

export default PasswordInput

EmailInput:

import React from 'react'

function EmailInput({ email, setEmail }) {
  const reg = /^\w ([\\.-]?\w )*@\w ([\\.-]?\w )*(\.\w{2,3}) $/

  function emailValidation(e) {
    const value = e.target.value
    setEmail(value)
    if (!reg.test(value)) {
      console.log('Enter a valid email')
    }
  }
  return (
    <div className='input-co'>
      <input
        type='email'
        id='email'
        placeholder=' '
        value={email}
        onChange={emailValidation}
      />
      <label htmlFor='email'>Email or phone number</label>
    </div>
  )
}

export default EmailInput

SigninInput:

import React from 'react'

function SigninInput({ handleSubmit }) {
  return <button className='signin' onClick={handleSubmit}>Sign in</button>
}

export default SigninInput

CodePudding user response:

Initialize the ref variables in the parent level and pass them to child as props through forward ref

function Login() {
  const emailRef = React.useRef()
  const passwordRef = React.useRef()

  return (
    <main>
      <div className='top'>
        <img src={logo} alt='Netflix' />
      </div>
      <section>
        <div className='si-card'>
          <h2>Sign In</h2>
          <EmailInput ref={emailRef} />
          <PasswordInput ref={passwordRef} />
          <SigninInput email={emailRef.current.value}  password={passwordRef.current.value} />
          <Rememberme />
        </div>
      </section>
    </main>
  )
}



export default EmailInput = React.forwardRef((ref) =>{ ....


function SigninInput({email = "",password = ""}) { ...
  • Related