Как интегрировать FileReader в Redux? - PullRequest
0 голосов
/ 26 мая 2018

Я прокомментировал, что много читаю официальную документацию, и я полностью понимаю концепцию и функционирование этого.Проблема в том, что это стоит мне немного дороже, чтобы применить это в реальности.Итак, я начал практиковать и наткнулся на то, что меня озадачило, я хочу создать кнопку, которая загружает изображение и показывает его предварительный просмотр.Однако это состоит из нескольких шагов, таких как:

  • проверка правильности загрузки изображения
  • создание fileReader
  • обновление статуса моего приложения (путьи имя изображения)
  • показать изображение

Это будет выглядеть так:

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

Я попытался создать действие и что полезная нагрузкаэто имя изображения и файл изображения, но я не знаю, куда поместить читателя ...

это мой компонент в настоящее время:

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>

Любые исправления приветствуются ... Спасибо!

Ответы [ 3 ]

0 голосов
/ 26 мая 2018

Почему бы вам просто не передать результат из 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 })

примечание - вы не можете передавать события в Redx, поскольку SyntheticEvents обнуляется .

Однако, если вы хотите сделать это вне компонента, вам нужно сделать это в действии создателя - не делайте это в редукторе, поскольку они должны быть чистыми без каких-либо побочных эффектов.Вам также понадобится какое-то промежуточное программное обеспечение для этого - самое простое, но достаточно для этого, будет 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;
  }
}
0 голосов
/ 03 августа 2018

У меня так получилось.Мне пришлось импортировать store, чтобы использовать dispatch в обещании.

создатель действия

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;

компонент (частично код, переплетная привязка)

// ...

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

export default connect(null, mapDispatchToProps)(YourComponentName);
0 голосов
/ 26 мая 2018

У меня похожая проблема, я бы так и сделал.Но я не уверен ...

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 }
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...