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;
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 ...
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!
Why don't you just pass result from FileReader to action creator?
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.
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. 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:
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;
}
}
I have a similar problem, I would do it that way. But I'm not sure...
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 }
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With