Image upload with ReactJS
Asked Answered
L

4

1

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!

Lemmons answered 13/3, 2017 at 7:1 Comment(2)
Read the image as data-uri instead of just keeping its path. Also, you can store the image in localstorage if you want to persist it across refreshes.Jeconiah
Try a library like npmjs.com/package/blob-util to handle image to data conversion for storage etc.Jeconiah
P
2

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

Parthenon answered 13/3, 2017 at 7:23 Comment(0)
C
1

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.

Cockshy answered 13/3, 2017 at 22:58 Comment(0)
A
0

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.

Anus answered 24/1, 2018 at 17:28 Comment(0)
C
0

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

Charlotte answered 24/1, 2018 at 18:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.