Search code examples
javascriptreactjsreact-props

How to get a variable back from a called component


I have a problem: I have my main class Input.js. A user can select a photo and upload it. The problem is I want to check if the user uploaded a photo or not when he press the button. For example I can give from Profilepic.js to Pic.js the picture as props. But how could I get back a variable? For example I want to set the variable in Profilepic.js and when the user I pressing the button the method onClick() should executed. Inside of this method it should check which value the variable isPreview has. And if the User hasnt uploaded a picture there should be a lable signaling him that he has to upload an image to continue.

Input.js

import React, { useState, useEffect } from 'react';
import { InputTags } from 'react-bootstrap-tagsinput';
import 'react-bootstrap-tagsinput/dist/index.css';
import './Input.css';
import Profilepic from './Profilepic';




const Input = () => {



    

  const checkAll = () => {
   
     // Call Preview from Profilepic.js
  }
  
  return (

    <div className="body-container">
            <Profilepic></Profilepic>
                <div className="row gutters">
                  <div className="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12">
                    <div className="text-right">
                      <button type="button" id="submit" name="submit" className="btn btn-primary" onClick={checkAll}>Speichern &amp; Weiter <i class="fas fa-paper-plane"></i></button>
                    </div>
                  </div>
                </div>
    </div>
  );
}

export default Input

Profilepic.js

import React, { useState } from "react";
import { Pic } from "./Pic.js";

const Profilpic = () => {
  const [preview, setPreview] = useState(null);
  const [isPreview, setIsPreview] = useState(false);

  const fileSelectedHandler = (event) => {
    try {
      console.log(event.target.files[0]);
      if (event.target.files[0].size > 70001680) {
        alert("File is too big! Wie Samys Dick");
      } else {
        let img = URL.createObjectURL(event.target.files[0]);
        setPreview(img);
        setIsPreview(true);
      }
    }
    catch (err) {

    }
  };



  return (
    <div>
      {preview ? (
        <div>
          <label htmlFor="myInput">
            <Pic preview={preview}></Pic>
          </label>
          <input
            id="myInput"
            style={{ display: "none" }}
            type={"file"}
            onChange={fileSelectedHandler}
          />
        </div>
      ) : (
        <div>
          <label htmlFor="myInput">
            <i className="fas fa-user-circle"></i>
          </label>
          <input
            id="myInput"
            style={{ display: "none" }}
            type={"file"}
            accept=".png,.jpg,.jpeg, .jfif"
            onChange={fileSelectedHandler}
          />
        </div>
      )}
    </div>
  );
};

export default Profilpic;

Pic.js

import React from "react";
import "./Photo.css";

const STYLES = ["btn--primary", "btn--outline", "btn--test"];

const SIZES = ["btn--medium", "btn--large"];

export const Pic = ({ preview }) => {
  //const checkButtonStyle = STYLES.includes(buttonStyle) ? buttonStyle : STYLES[0];
  //const checkButtonSize = SIZES.includes(buttonSize) ? buttonSize : SIZES[0];
  // Püsh for Samy
  return (
    <div class="profilepic">
      <img
        class="profilepic__image"
        src={preview}
        width="120"
        height="120"
        alt="Profibild"
      />
      <div class="profilepic__content">
        <span class="profilepic__icon">
          <i class="fas fa-camera"></i>
        </span>
        <span class="profilepic__text">Profilbild ändern</span>
      </div>
    </div>
  );
};

Description of the Problem


Solution

  • You can use the useImperativeHandle. This requires a bit of a wrapping of

    Profilepic

    import React, { forwardRef, useImperativeHandle, useState } from "react";
    import { Pic } from "./Pic.js";
    
    function Profilepic(props, ref) {
      const [preview, setPreview] = useState(null);
      const [isPreview, setIsPreview] = useState(false);
    
      useImperativeHandle(
        ref,
        () => ({ isPreview }),
        [isPreview]
      );
    
      ...
    
      return (
        ...
      );
    };
    
    export default forwardRef(Profilepic);
    

    Input

    import React, { useState, useEffect, useRef } from 'react';
    import Profilepic from './Profilepic';
    
    const Input = () => {
      const profilePicRef = useRef();
    
      const checkAll = () => {
        // access profilePicRef.current.isPreview
      }
      
      return (
        <div className="body-container">
          <Profilepic ref={profilePicRef} />
          ...
            <button
              type="button"
              id="submit"
              name="submit"
              className="btn btn-primary"
              onClick={checkAll}
            >
              Speichern &amp; Weiter <i class="fas fa-paper-plane" />
        </button>
          ...
        </div>
      );
    }