2016-09-26 3 views
4

파일을 업로드하려고 할 때 상점에 올바른 값을 얻을 수 없습니다. 파일 내용 대신에 나는 { 0: {} }과 같은 것을 얻습니다. 내가 REDUX 형태의 V5를 사용하여 만들어진 발견 된 웹redux-form을 사용하여 파일을 업로드하는 방법은 무엇입니까?

const renderInput = field => (
    <div> 
    <input {...field.input} type={field.type}/> 
    { 
     field.meta.touched && 
     field.meta.error && 
     <span className={styles.error}>{field.meta.error}</span> 
    } 
    </div> 
); 

render() { 

    ... 

    <form className={styles.form} onSubmit={handleSubmit(submit)}> 
    <div className={styles.interface}> 
     <label>userpic</label> 
     <Field 
     name="userpic" 
     component={renderInput} 
     type="file" 
     /> 
    </div> 
    <div> 
     <button type="submit" disabled={submitting}>Submit</button> 
    <div> 
    </form> 

    ... 

} 

모든 예제 : 여기에 코드입니다.

어떻게하면 redux-form v6에서 파일 입력을 할 수 있습니까?

답변

7

Dropzone

import React, {Component, PropTypes} from 'react'; 
import Dropzone from 'react-dropzone'; 
import { Form } from 'elements'; 
import { Field } from 'redux-form'; 

class FileInput extends Component { 
    static propTypes = { 
    dropzone_options: PropTypes.object, 
    meta: PropTypes.object, 
    label: PropTypes.string, 
    classNameLabel: PropTypes.string, 
    input: PropTypes.object, 
    className: PropTypes.string, 
    children: PropTypes.node, 
    cbFunction: PropTypes.func, 
    }; 

    static defaultProps = { 
    className: '', 
    cbFunction:() => {}, 
    }; 

    render() { 
    const { className, input: { onChange }, dropzone_options, meta: { error, touched }, label, classNameLabel, children, name, cbFunction } = this.props; 

    return (
     <div className={`${className}` + (error && touched ? ' has-error ' : '')}> 
     {label && <p className={classNameLabel || ''}>{label}</p>} 
     <Dropzone 
      {...dropzone_options} 
      onDrop={(f) => { 
      cbFunction(f); 
      return onChange(f); 
      }} 
      className="dropzone-input" 
      name={name} 
     > 
      {children} 
     </Dropzone> 
     {error && touched ? error : ''} 
     </div> 
    ); 
    } 
} 
export default props => <Field {...props} component={FileInput} />; 

와 REDUX 폼 입력 래퍼의 내 예는이 기능을 사용하려면 (PropTypes를 사용하지 않고 그것을 할

<FileInput 
name="add_photo" 
label="Others:" 
    classNameLabel="file-input-label" 
    className="file-input" 
    dropzone_options={{ 
    multiple: false, 
    accept: 'image/*' 
    }} 
> 
    <span>Add more</span> 
</FileInput> 
+2

'onDrop' 함수에서받은 파일은 서버에 보내기 전에'FileReader'로 읽어야한다고 생각합니다. 그렇지 않으면 그건 쓸데 없어. 원래 질문에 완전히 대답하는 데 도움이된다면 여기에 예제를 추가 할 수 있습니다. –

0

또 다른 방법과 미리보기 이미지를 렌더링합니다 아래의 예는 React 16+ 구문을 사용하며 API로 보내기 위해 하나의 이미지 파일 만 허용하지만 약간의 미세 조정을 통해 여러 이미지 및 기타 입력 필드로 확장 할 수도 있습니다.

renderDropZone.js (DROPZONE 성분)

import map from 'lodash/map'; 
import React, { Fragment } from 'react'; 
import DropZone from 'react-dropzone'; 

const RenderDropZone = ({ 
    errors, 
    handleOnDrop, 
    input, 
    imageFileToUpload, 
    label, 
    touched 
}) => { 
    const renderImagePreview =() => { 
    map(imageFileToUpload, ({ name, preview, size }) => { 
     return [ 
     <li key="imagePreview> 
      <img src={ preview } alt={ name } /> 
     </li>, 
     <li key="imageDetails"> 
      { name } - { size } bytes 
     </li> 
     ] 
    }); 
    }; 

    return [ 
    <Fragment> 
     <DropZone 
     accept="image/jpeg, image/png, image/gif, image/bmp" 
     className="upload-container" 
     onDrop={handleOnDrop} 
     onChange={fileToUpload => input.onChange(fileToUpload)} 
     > 
     {imageFileToUpload.length > 0 
      ? <ul className="uploaded-images-container"> 
       { renderImagePreview() } 
      </ul> 
      : <p>Click or drag image file to this area to upload.</p> 
     } 
     </DropZone> 
     { touched && error && <div className="error-handlers">{ error }</div> } 
     <label className="form-label">{ label }</label> 
    </Fragment> 
); 
}; 

export default RenderDropZone; 

UploadForm.js (돌아 오는 폼 성분)

import React, { Component } from 'react'; 
import { Form, Field, reduxForm } from 'redux-form';; 
import RenderDropZone from './renderDropZone'; 

const imageIsRequired = value => ({ !value ? 'Required' : undefined }); 

class UploadForm extends Component { 
    state = { imageFileToUpload: [] }; 

    handleOnDrop = newImage => this.setState({ imageFileToUpload: newImage }); 

    render() { 
    const { handleSubmit, pristine, reset, submitting } = this.props; 

    return (
     <div className="form-container col-xs-12"> 
     <h1>Upload An Image</h1> 
     <hr /> 
     <Form onSubmit={handleSubmit}> 
      <Field 
      name="imageToUpload" 
      component={({ input, meta: { error, touched } }) => 
       <RenderDropZone    
       error={error} 
       handleOnDrop={this.handleOnDrop} 
       input={input} 
       imageFileToUpload={this.state.imageFileToUpload} 
       label="Upload Image" 
       touched={touched} 
       /> 
      } 
      type="file" 
      placeholder="Upload Image" 
      validate={[imageIsRequired]} 
      />   
      <button 
      type="submit" 
      className="submit btn btn-primary" 
      disabled={submitting} 
      > 
       Submit 
      </button> 
      <button 
      type="button" 
      className="clear-values btn btn-danger" 
      disabled={pristine || submitting} 
      onClick={() => 
       this.setState({ imageFileToUpload: [] }); 
       reset(); 
      } 
      > 
       Clear 
      </button> 
     </Form> 
     </div> 
    ); 
    }; 
}; 

export default reduxForm({ 
    form: 'UploadForm' 
})(UploadForm); 

renderUploadForm.js (위에서 모두를 취하고 형태를 도시 사용자; 제출 된 돌아 오는 형태 소품)

import React, { Component } from 'react'; 
import { reduxForm } from 'redux-form'; 

import createFormData from './configFormData'; 
import UploadForm from './UploadForm'; 

const RenderUploadForm =() => { 
    const handleFormSubmit = formProps => { 
    const formData = createFormData(formProps); 

    /* create an AJAX POST request here with the created formData */ 

    }; 

    return <UploadForm onSubmit={formProps => handleFormSubmit(formProps)}/> 
}; 

export default reduxForm({ 
    form: 'UploadForm' 
})(RenderUploadForm); 

configFormData.js (API가 결국 AJAX POST 요청에 따라 읽기 위해 돌아 오는 형태 소품에서 FormData를 생성)

const createFormData = ({ imageToUpload }) => { 
    const fd = new FormData(); 
    fd.append('imageFile', imageToUpload[0]); 

    /* 
     Examples of appending other inputs -- the specified name inside 
     the single quotes can be named anything, while the second 
     parameter MUST be the "name" specified in the Redux Form component: 

     <Field name='textinputName' type='text'>Example</Field> 

     fd.append('nameofTextInput', textinputName); 
     fd.append('nameofTextArea', textareaName); 
     fd.append('nameofCheckBox', checkboxName); 
     ...etc 
    */ 

    return fd; 
}; 

export default createFormData; 

예를 포착 할뿐만 아니라 : enter image description here 예/미리보기 W : enter image description here

0

같은 필드 구성 요소 만들기 :

import React, {Component} from 'react' 

export default class FieldFileInput extends Component{ 
    constructor(props) { 
    super(props) 
    this.onChange = this.onChange.bind(this) 
    } 

    onChange(e) { 
    const { input: { onChange } } = this.props 
    onChange(e.target.files[0]) 
    } 

    render(){ 
    const { input: { value } } = this.props 
    const {input,label, required, meta, } = this.props //whatever props you send to the component from redux-form Field 
    return(
    <div><label>{label}</label> 
    <div> 
     <input 
     type='file' 
     accept='.jpg, .png, .jpeg' 
     onChange={this.onChange} 
     /> 
    </div> 
    </div> 
    ) 
} 
} 

이 구성 요소를 필요한 곳에있는 필드 구성 요소에 전달하십시오. 간단한 파일 업로드 기능을 사용하는 경우 추가 Dropzone 또는 다른 라이브러리가 필요 없습니다.

관련 문제