web-dev-qa-db-fra.com

ReactJS: Comment gérer le téléchargement d'images / fichiers avec Formik?

Je crée une page de profil pour mon site en utilisant ReactJS. Maintenant, ma question est de savoir comment télécharger l'image de la machine locale et l'enregistrer dans la base de données et l'afficher également dans la page de profil

import React, {Component} from 'react';
import { connect } from 'react-redux';
import { AccountAction } from '../../actions/user/AccountPg1Action';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

class AccountInfo extends Component {
  constructor(props) {
    super(props) 
    this.state = {
      currentStep: 1,
      userAccountData: {
        userid: '',
        useravtar: '',
        attachement_id: '',
   }
  }
 }

handleFileUpload = (event) => {
  this.setState({useravtar: event.currentTarget.files[0]})
};

handleChange = event => {
    const {name, value} = event.target
    this.setState({
      [name]: value
    })    
  }

handleSubmit = event => {
    let that = this;
    const { AccountAction } = that.props;
    event.preventDefault();

    let accountInputs = {
      userid: 49,
      useravtar: that.state.image,
      attachement_id: 478,
}
    that.setState({
      userAccountData: accountInputs,
    })

    AccountAction(accountInputs)
  }
AccountInfoView = () => {
console.log(this.state.useravtar)
    return (
      <section id="account_sec" className="second_form">
      <div className="container">
      <React.Fragment>
        <Formik
          initialValues={‌{
            file: null,
            email: '',
            phone: ''
          }}
          validationSchema={accountInfoSchema}
          render={(values) => {
          return(
        <Form onSubmit={this.handleSubmit}>
        <Step1 
          currentStep={this.state.currentStep} 
          handleChange={this.handleChange}
          file= {this.state.useravtar}
          handleFileUpload={this.handleFileUpload}
          />
          </Form>
        );
      }}
      />
      </React.Fragment>
      )
  }

  render() {    

    return (
      <div>{this.authView()}</div>
    )
  }
}

function Step1(props) {
console.log(props.useravtar)
  if (props.currentStep !== 1) {
    return null
  } 

  return(
    <div className="upload">
        <label htmlFor="profile">
          <div className="imgbox">
            <img src="images/trans_116X116.png" alt="" />
            <img src={props.useravtar} className="absoImg" alt="" />
          </div>
        </label>
<input id="file" name="file" type="file" accept="image/*" onChange={props.handleFileUpload}/>
        <span className="guide_leb">Add your avatar</span>
      </div>
  )
}

Lorsque je console dans l'action handleChange pour event.target.file [0], il répond avec undefined.

De plus, en effectuant une action console.log(this.state.useravtar) dans handleSubmit, elle affiche un chemin d'accès comme c:/fakepath/imgname.jpg

P.S: J'ai plusieurs formulaires, donc je l'utilise de manière Step. Et j'utilise Redux Reducer pour stocker les données.

J'ai fait référence au lien this mais mon exigence ne ressemble pas à ceci.

9
aananddham

Formik ne prend pas en charge le téléchargement de fichiers par défaut, mais vous pouvez essayer ce qui suit

<input id="file" name="file" type="file" onChange={(event) => {
  setFieldValue("file", event.currentTarget.files[0]);
}} />

Ici "file" représente la clé que vous utilisez pour conserver le fichier

Et sur soumettre, vous pouvez obtenir le nom de fichier, la taille, etc. pour le fichier en utilisant

onSubmit={(values) => {
        console.log({ 
              fileName: values.file.name, 
              type: values.file.type,
              size: `${values.file.size} bytes`
            })

Si vous souhaitez définir le fichier dans l'état des composants, vous pouvez utiliser

onChange={(event) => {
  this.setState({"file": event.currentTarget.files[0]})};
}}

Selon votre code, vous devez gérer le téléchargement des fichiers comme ci-dessous

Dans AccountInfo, ajoutez une fonction pour gérer le téléchargement de fichiers

handleFileUpload = (event) => {
this.setState({WAHTEVETKEYYOUNEED: event.currentTarget.files[0]})};
}

Et passez la même fonction au composant Step1 que ci-dessous

    <Step1 
      currentStep={this.state.currentStep} 
      handleChange={this.handleChange}
      file= {this.state.image}
      handleFileUpload={this.handleFileUpload}
      />

Dans le composant Step1 où vous téléchargez le fichier, modifiez l'entrée comme

<input id="file" name="file" type="file" accept="image/*" onChange={props.handleFileUpload}/>

Si vous avez besoin de prévisualiser l'image téléchargée, vous pouvez créer un blob et le passer comme source pour l'image comme ci-dessous

<img src={URL.createObjectURL(FILE_OBJECT)} /> 
7