Kavindu N
Kavindu N

Reputation: 383

Image upload with ReactJS

I’m building this ReactJS application which where I want to upload an image using a click of a button and take it to the next view which is the cropping window and then after cropping it, then I can upload it to the server.

The issue which I’m having right now is how to take an image from 1 view to another view without uploading it to the server?

I tried taking the image path, but unfortunately when the UI refreshes, the path will get flushed.

So, what are the options which I can use in this situation.

Thank you!

Upvotes: 1

Views: 5545

Answers (4)

SrThompson
SrThompson

Reputation: 5748

You need to read the image file as a blob and keep it on a parent component which would be in charge of rendering the different components for image manipulation. In some file input element you need a function like this to handle the image selected by the user

  handleImageChange = e => {
    e.preventDefault();

    const reader = new FileReader();
    const file = e.target.files[0];

    reader.onloadend = () => {
        this.setState({
            file,
            imagePreview: reader.result
        });
    };

    if (file) {
        reader.readAsDataURL(file);
    }
  };

Then you can put that file on as many components as you like. If you want it to persist between refreshes you need to put the file on localStorage or indexedDB

Upvotes: 0

Rex
Rex

Reputation: 376

The IndexedDB API is great for client side, large file storage.

Using IndexedDB: MDN

Checkout LocalForage. It makes using IndexedDB easy, similar to using localStorage.

This solution would allow you to store an image client side with all major browsers. You would be able to perform operations on it from a global store and when you wanted to, you would be able to send it to the server.

It also provides your application with an offline cache, where the image would not be lost between sessions or network connections.

Upvotes: 0

Antoine Trouve
Antoine Trouve

Reputation: 1273

So you want to keep your image infos between view. By "view", do you mean a different HTML page? I guess a more standard way of doing things would be to:

  • store the file content/path in a state (e.g. redux state)
  • use client-side router (e.g. react-router) to change the view while keeping the state

If you have never used client-side routing, it looks like that (with react-router):

import { Router, Route, browserHistory } from 'react-router'

// Iy you use redux to handle the state
import { createStore } from 'redux'
import myReducer from 'my-reducer'
const store = createStore(myReducer) 
const history = syncHistoryWithStore(browserHistory, store)

// Your view components
function Top(props) { ... }
function UploadImage(props) { ... }
function EditImage(props) { ... }

// The Router itself
ReactDOM.render(
  <Router history={history}>
    <Route path="/" component={Top} >
      <Route path="upload-image" component={UploadImage} />
      <Route path="edit-image" component={EditImage} />
    </Route>
  </Router>)

If you have never used redux before, you can use it this way:

First, create the reducer

import { combineReducers } from 'redux'

const myReducer = combineReducers({ imagePath })

// This is called a reducer function
function imagePath(oldState = "", action) {
  switch(action.type) {
  case 'SET_PATH':
    return action.payload
  }
}

Next, connect your component to get the state value (e.g. UploadImage)

const ReduxUploadImage = connect(function(state) {
  return {
    imagePath: state.imagePath
  }
})(UploadImage)

Now if you use ReduxUploadImage instead of UploadImage, you can access imagePath through props.imagePath. The connect function also add a dispatch function to your props.

Finally, you can set the path by calling within your component (but not the render function itself: this would be an anti-pattern)

props.dispatch( { type: 'SET_PATH', payload: "the_path" } )

Finally, it is easy to persist the redux state between pages or refresh using dedicated middleware.

Upvotes: 1

Michal Cholewiński
Michal Cholewiński

Reputation: 464

Yesterday I worked on similar case. I'm using react-dropzone which returns uploaded files, one of the field in file object is 'preview', it contains uri of currently uploaded file (It's probably cached somehow, but I didn't investigate it yet). In another view you just doing

Upvotes: 2

Related Questions