Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Passing an Array from one UseState to Another

I’m currently trying to figure out how to pass an array from one useState object to another across two different components. In my first useState I have an array called imagesOriginal, which gets filled with file paths dynamically to various different images like in the following:

[
    "https://source.unsplash.com/WLUHO9A_xik/900x900",
    "https://source.unsplash.com/R4K8S77qtwI/900x900",
    "https://source.unsplash.com/jJGc21mEh8Q/900x900"
]

In my App.js, I construct it like so.

import React, { useCallback, useState } from 'react';
import ShowImage from './ShowImage.jsx';
import DropBox from './DropBox.js';

function App() {
    const [imagesOriginal, setImages] = useState([]);

    const onDrop = useCallback((acceptedFiles) => {
        acceptedFiles.map((file, index) => {
            const reader = new FileReader();

            reader.onload = function (e) {
                setImages((prevState) => [
                    ...prevState,
                    { id: index, src: e.target.result },
                ]);
            };

            reader.readAsDataURL(file);
            return file;
        });
    }, []);

    return (
        <div className="App">
            <div class="parent">
                <div>
                    <h3>Originals</h3>
                    <DropBox onDrop={onDrop} />
                    <ShowImage images={imagesOriginal}/>
                </div>
            </div>
        </div>
    );
}

export default App;

The main issue comese in the ShowImage.jsx, where I want to pass that array of images to another useState, as I need to use both the array and the setItems to sort the array with a new order.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import React, { useState } from 'react';
import {
    DndContext,
    closestCorners,
    MouseSensor,
    TouchSensor,
    DragOverlay,
    useSensor,
    useSensors,
} from '@dnd-kit/core';
import "./ShowImage.css"
import {arrayMove, SortableContext} from '@dnd-kit/sortable';
import {SortablePhoto} from './SortablePhoto.jsx';

const ShowImage = ({images}) => {

    const [items, setItems] = useState([]);
    setItems([...images]);
    const [activeId, setActiveId] = useState(null);
    const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor));

    return(
        <div class="scroll">
            <DndContext
                sensors={sensors}
                collisionDetection={closestCorners}
                onDragStart={handleDragStart}
                onDragOver={handleDragOver}
                onDragEnd={handleDragEnd}
                onDragCancel={handleDragCancel}
            >
                <SortableContext items={items} strategy={() => {}}>
                    <div columns={1}
                        style={{
                        display: "grid",
                        gridAutoRows: `100px`,
                        gridGap: 10
                        }}
                    >
                        {items.map((url, index) => (
                            <SortablePhoto key={url.src} url={url.src} index={index}/>
                        ))}
                    </div>
                </SortableContext>
            </DndContext>
        </div>
    );

    function handleDragStart(event) {
        setActiveId(event.active.id);
    }
    
    function handleDragOver(event) {
        const {active, over} = event;
    
        if (active.id !== over.id) {
          setItems((items) => {
            const oldIndex = items.indexOf(active.id);
            const newIndex = items.indexOf(over.id);
    
            return arrayMove(items, oldIndex, newIndex);
          });
        }
    }
    
    function handleDragEnd(event) {
        setActiveId(null);
    }
    
    function handleDragCancel() {
        setActiveId(null);
    }
};

export default ShowImage;

I’ve tried using the line setItems([...images]); to try and pass the new items in, and also const [items, setItems] = useState(images);, but It never seems to update the items array. I’m probably doing something really stupid, but any help would be greatly appreciated.

>Solution :

You can create a function in your App component that wraps your setItems state modifier and pass this function as a prop to your nested ShowImage component where you could use it to manipulate the state. This way you won’t need to maintain 2 different states.

// App.js

function App() {
    const [imagesOriginal, setImages] = useState([]);
    const setImagesWrapper = useCallback(val => {
      setImages(val);
    }, [setImages]);
    //...

    return (
        <div className="App">
            <div class="parent">
                <div>
                    <h3>Originals</h3>
                    <DropBox onDrop={onDrop} />
                    <ShowImage images={imagesOriginal} setImages={setImagesWrapper}/>
                </div>
            </div>
        </div>
    );
}

export default App;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading