简体   繁体   English

如何在Redux中集成FileReader?

[英]How to integrate FileReader in Redux?

I commented that I was reading the official documentation a lot, and I fully understand the concept and functioning of this. 我评论说我正在阅读官方文档,我完全理解这个的概念和功能。 The problem is that it costs me a bit more to apply it in reality. 问题是在现实中应用它会花费我多一点。 So I started to practice and I came across something that puzzled me, I want to create a button that loads an image and shows the preview of it. 所以我开始练习,我遇到了令我困惑的事情,我想创建一个加载图像的按钮并显示它的预览。 However, this consists of some steps such as; 但是,这包括一些步骤,如;

  • verify that the image has been uploaded correctly 验证图像是否已正确上载
  • create a fileReader 创建一个fileReader
  • update the status of my application (path, and name of the image) 更新我的应用程序的状态(路径和图像的名称)
  • show the image 显示图像

This would look like this: 这看起来像这样:

onImageChange(event) {
    if (event.target.files && event.target.files[0]) {
        let reader = new FileReader();
        let file = event.target.files[0];

        reader.onloadend = () => {
            this.setState({
                imageFile: file,
                imageName: file.name
            });
        }   
        reader.readAsDataURL(file)
    }
}

I tried to create an action and that the payload is image Name and imageFile but I do not know where to put the reader ... 我试图创建一个动作,有效载荷是图像名称和imageFile但我不知道在哪里放读者...

this is my component currently: 这是我目前的组件:

 import React, { Component } from "react"; import ImageModalForm from "../../../Commons/components/ImageModalForm"; import { connect } from "react-redux"; import { bindActionCreators } from "redux"; import { loadImage } from "../../actions"; const faceImage = require("../../../../img/face5.gif"); class ThumbnailComp extends Component { onImageChange(event) { if (event.target.files && event.target.files[0]) { let reader = new FileReader(); let file = event.target.files[0]; reader.onloadend = () => { this.setState({ imageFile: file, imageName: reader.result }); }; reader.readAsDataURL(file); } } render() { return ( <ImageModalForm imageFile={this.props.imageFile} imageName={this.props.imageName} onImageChange={this.onImageChange} /> ); } } function mapStateToProps(state) { return { image: state.image }; } function mapDispatchToProps(dispatch) { return bindActionCreators({ loadImage }, dispatch); } export default connect(mapStateToProps, mapDispatchToProps)(ThumbnailComp); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 

Any correction is welcome ... Thanks! 欢迎任何更正...谢谢!

I have a similar problem, I would do it that way. 我有类似的问题,我会这样做。 But I'm not sure... 但我不确定......

action.js action.js

function loadImage(event){
  if (event.target.files && event.target.files[0]){
   let file = event.target.files[0];
   let fileName = file.name
  }
  return {
   type: LOAD_IMAGE,
   payload: { imageFile: file, imageFileName: fileName }
 }
}

Why don't you just pass result from FileReader to action creator? 为什么不将结果从FileReader传递给动作创建者?

onImageChange(event) {
    if (event.target.files && event.target.files[0]) {
      let reader = new FileReader();
      let file = event.target.files[0];

      reader.onloadend = () => {
        this.props.loadImage(reader.result)
      };
      reader.readAsDataURL(file);
    }
}

// action creator
const loadImage = (result) => ({ type: LOAD_IMAGE, result })

side note - you can't pass events to redux as SyntheticEvents gets nullified . 旁注 - 当SyntheticEvents无效时,您无法将事件传递给redux。

However, if you want to make this outside of component you need to do it in action creator - don't do it in reducer as they need to be pure without any side-effects. 但是,如果你想在组件之外做这个,你需要在动作创建器中进行 - 不要在reducer中这样做,因为它们需要是纯净的而没有任何副作用。 You will also need some kind of middleware to do it - the simplest yet enough for this would be redux-thunk - which allows you to return a function from your action creators: 你还需要一些中间件才能做到这一点 - 最简单的就是redux-thunk - 它允许你从你的动作创建者那里返回一个函数:

onImageChange(event) {
    if (event.target.files && event.target.files[0]) {
      let file = event.target.files[0];
      this.props.loadImage(file)
    }
}

// action creator
const loadImage = file => dispatch => {
  let reader = new FileReader();

  reader.onloadend = () => {
    dispatch({
      type: 'SET_IMAGE_IN_REDUCER',
      image: reader.result
    });
  };
  reader.readAsDataURL(file);
}


// example reducer
const initialState = { image: null };
function reducer(state = initialState, action) {
  switch(action.type) {
    case 'SET_IMAGE_IN_REDUCER': 
      return { ...state, image: action.image }
    ...
    default:
      return state;
  }
}

It worked for me this way. 它以这种方式为我工作。 I had to import store to use dispatch in the promise. 我必须导入store才能在promise中使用dispatch

action creator 行动创造者

import store from '../store/index';

export const UPLOAD_FILE = 'UPLOAD_FILE';

export function uploadTextFile(file) {
    new Promise((resolve, reject) => {
        let reader = new FileReader();
        reader.onloadend = () => { resolve(reader.result) };
        reader.readAsText(file);
    }).then(result => store.dispatch({
        type: UPLOAD_FILE,
        payload: result}
    ));
}

store 商店

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

import rootReducer from '../reducers/index';

const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;

component (partly code, redux binding) 组件(部分代码,redux绑定)

// ...

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ uploadTextFile }, dispatch);
}

export default connect(null, mapDispatchToProps)(YourComponentName);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM