2016-09-26 106 views
4

嘗試上傳文件時,我無法在商店中獲得正確的值。我得到了類似{ 0: {} }的文件內容。 下面的代碼:如何使用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> 

    ... 

} 

所有,我發現使用終極版型的V5作了網絡上的例子。

如何以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的形式輸入包裝的例子來使用它:

<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

另一種方式來做到這一點,而不必使用PropTypes,將渲染預覽圖像(下面的例子使用React 16+語法,只接受一個圖像文件發送給API;但是,通過一些小調整,還可以縮放到多個圖像和其他字段輸入:

renderDropZone.js(懸浮窗成分)

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(Redux的表單組件)

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(從上面取一切和顯示的形式用戶;以及,捕捉提交Redux的表格道具)

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(從終極版形態道具創建FORMDATA爲API來根據AJAX POST請求最終讀取)

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> 
    ) 
} 
} 

將此組件傳遞到您需要的Field組件。如果您使用簡單的文件上傳功能,則無需額外的Dropzone或其他庫。