Как сделать так, чтобы данные в массиве не сбрасывались после каждого добавления файла

Рейтинг: 0Ответов: 1Опубликовано: 05.05.2023

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

Приложение написано на React + TypeScript.

import React, { useRef, useEffect, useState, useContext } from 'react';
import '../style/Modal.scss';
import { Context } from '..';
import { observer } from 'mobx-react-lite';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { AiOutlineFileText, AiOutlinePlus } from 'react-icons/ai';
import { RxCross2 } from 'react-icons/rx';
type ModalProps = {
  show: boolean;
  onClose: () => void;
  course_id:any;
  task:any;
};

const Modal: React.FC<ModalProps> = ({ show, onClose, course_id, task }) => {
    const {store} = useContext(Context)
    const test: File[] = [];
    const modalRef = useRef<HTMLDivElement>(null);
    const [colorz, setColorz] = useState<any>();
    const [edit, setEdit] = useState<boolean>(false);
    const [colorHex, setColorHex] = useState<any>();
    const [colorPicker, setColorPicker] = useState<boolean>(false);
    const [titleClass, setTitleClass] = useState<string>()
    const [chapter, setChapter] = useState<string>()
    const [object, setObject] = useState<string>()
    const [audience, setAudience] = useState<string>()
    const [content, setContent] = useState('');
    const fileInputRef = useRef<HTMLInputElement>(null);
    const [selectedFile, setSelectedFile] = useState<any>()
    
    const handleFileSelected = (event: React.ChangeEvent<HTMLInputElement>) => {
        const { files } = event.target;
        const selectedFiles = files as FileList;
        const t = []
        for(var i = 0; i < selectedFiles?.length; i++){
            t.push(selectedFiles?.[i])
            test.push(selectedFiles?.[i])
        }
        console.log(test)
        setSelectedFile(test)
    };
  const modules = {
    toolbar: [
        [{ 'header': [1, 2, false] }],
        ['bold', 'italic', 'underline', 'strike', 'code'],
        [{ 'color': [] }, { 'background': [] }],
        [{ 'font': [] }],
        [{ 'align': [] }],
        [{ 'list': 'ordered' }, { 'list': 'bullet' }],
        ['link', 'image'],
        ['clean']
        ]
    };
    useEffect(() => {
        if(task.id)
            setEdit(true)
        const handleOutsideClick = (event: MouseEvent) => {
        if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
            onClose();
        }
        };
        if (show) {
        document.addEventListener('mousedown', handleOutsideClick);
        }

        return () => {
        document.removeEventListener('mousedown', handleOutsideClick);
        };
    
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

    const formats = [
    'header',
    'bold', 'italic', 'underline', 'strike', 'code',
    'color', 'background', 'font', 'align',
    'list', 'bullet',
    'link', 'image'
    ];

    function handleChange(value: string) {
    setContent(value);
    }

    const handleClose = () => {
    onClose();
    };

    const [date, setDate] = useState<Date | null>(null);

    const handleChangeDate = (date: Date | null) => {
      setDate(date);
    };
  return (
    <div className='class-modal'>
        <div className="modal-backdrop">
            <div className="modal" ref={modalRef}>
            <div className="modal-header">
                {edit&&(
                <h1 style={{color:'black'}}>Изменить задание</h1>
                )}
                {!edit&&(
                <h1>Создать задание</h1>
                )}
                <button className="modal-close" onClick={handleClose} style={{marginTop:'0.5rem', marginLeft:'-60px'}}>
                    &times;
                </button>
            </div>
            <div className="modal-body">
            <div className="continput">
                    <p>Название:</p>
                    <input type="text" placeholder='Название' className='inputlog' autoComplete='false'
                    value={titleClass} onChange={(e)=>setTitleClass(e.target.value)}/>
                </div>
                <div className="continput">
                    <p>Инструкции:</p>
                    <ReactQuill
                    value={content}
                    onChange={handleChange}
                    modules={modules}
                    formats={formats}
                    style={{width:'100%'}}/>
                </div>
                <div className="continput">
                    <p>Баллы:</p>
                    <input type="number" placeholder='Баллы' className='inputlog' autoComplete='false'
                    value={object} onChange={(e)=>setObject(e.target.value)}/>
                </div>
                <div className="continput">
                    <p>Дата сдачи:</p>
                    <DatePicker
                        id="dateTimePicker"
                        className="inputlog"
                        selected={date}
                        onChange={handleChangeDate}
                        showTimeSelect
                        dateFormat="Pp"
                    />
                </div>
                <div className="continput">
                    <p>Дополнительные файлы: </p>
                    <div className="add-photo" style={{width:'100%', height:'60px'}}>
                    <div className="file-input" style={{marginTop:'10px'}}>
                        <label htmlFor="file-input" style={{width:'30px', height:'30px'}}>
                        <AiOutlinePlus style={{fontSize:'18px', paddingBottom:'2px'}}/>
                        </label>
                        <input
                        ref={fileInputRef}
                        id="file-input"
                        type="file"
                        onChange={handleFileSelected}
                        accept='*'
                        multiple
                        />
                    </div>
                    </div>
                    {selectedFile&&(
                        <div style={{width:'100%'}}>
                            {selectedFile.map((t:any)=>(
                                <div className="body-file"
                                style={{display:'flex',
                                border:'2px solid #AEB5C8',
                                marginTop:'10px',
                                width:'100%',
                                borderRadius:'5px', 
                                background:'#AEB5C8',
                                color:'white'}}>
                                    <AiOutlineFileText style={{fontSize:'20px',
                                    marginTop:'16px', marginRight:'10px'}}/>
                                    <p style={{width:'90%'}}>{t.name}</p>
                                    <RxCross2 style={{marginTop:'20px'}}/>
                                </div>
                            ))}
                        </div>
                    )}
                </div>
                <div className="btn-cnt" >
                    <button className='cancel' onClick={handleClose}>Отменить</button>
                    <button className='save'>Сохранить</button>
                </div>
            </div>
            </div>
        </div>
    </div>
  );
};

export default observer(Modal);

Помогите пожалуйста ^_^

Ответы

▲ 1Принят

Вам необходимо добавлять значения к переменной состояния и её же сохранять.

Меняем начальное состояние переменной selectedFile на пустой массив:

const [selectedFile, setSelectedFile] = useState<any>([]);

Переделываем функцию handleFileSelected:

const handleFileSelected = (event: React.ChangeEvent<HTMLInputElement>) => {
  const selectedFiles = event.target.files as FileList;
  setSelectedFile((prev) => {
    for (let i = 0; i < selectedFiles?.length; i++) {
      prev.push(selectedFiles[i])
    }
    return prev; // Если реагировать не будет, то return [ ...prev ]
  })
};

Данная функция вызывает setSelectedFile в которой добавляет новые элементы к текущему состоянию переменной(массиву) selectedFile и возвращает новый массив с новыми элементам.