Почему не срабатывает onChange в инпуте React?
Делаю что-то вроде сайта для хранения файлов. Для их загрузки в инпуте, при выборе файлов, вызывается метод add из кастомного хука.
import {useState} from 'react';
const isDirectory = maybeFile => !maybeFile.type && maybeFile.size % 4096 === 0;
const generateId = () => (performance.now().toString(36) +
Math.random().toString(36)).replace(/\./g, '');
export const useFiles = (initialState={}) => {
const [value, setValue] = useState(initialState);
const add = newFiles => {
const filteredFiles = newFiles.filter(file => !isDirectory(file));
const result = {};
filteredFiles.forEach(file => {
result[generateId()] = file;
});
setValue({...value, ...result});
};
const remove = fileId => {
let filesCopy = {...value};
delete filesCopy[fileId];
setValue(filesCopy);
};
return {value, add, remove};
};
И я не могу понять, почему если загрузить несколько файлов на сайт, потом их поудалять с помощью remove, который срабатывает при нажатии на кнопочку удаления рядом с файлом, а потом заново попытаться загрузить эти же файлы, то onChange в инпуте не срабатывает. Но если выбрать какие-то другие файлы, то все сработает и опять же при их удалении их нельзя будет еще раз загрузить, но уже станет возможно предыдущие.
В консоли никаких ошибок не пишет. Дебагом не получается проверить, потому что сам onChange не срабатывает.
Еще небольшое пояснение:
Вот эти файлы из хука отрисовываются с помощью компонента файла в map и внутри этого компонента я использую еще 1 кастомный хук, в котором более удобно хранятся id файла и сам файл. Может ли быть проблема в этом возможно лишнем хуке?
import {useState} from "react";
export const useFile = (fileId, file) => {
const [value, setValue] = useState(file);
const [id, setId] = useState(fileId);
return {value, id};
};
Ответы (1 шт):
Так и не понял в чем проблема, но попробовал заменить эти 2 хука на useReducer и все стало отлично работать
import React, {useReducer, createContext} from 'react';
import {reducer} from './reducer';
const filesToExpand = ['text/plain', 'image/jpeg', 'image/png',
'video/mp4', 'video/mov', 'video/ogv', 'video/webm'];
export const FilesContext = createContext(null);
export const Provider = ({children}) => {
const [state, dispatch] = useReducer(reducer, []);
const value = {
files: state,
add: file => dispatch({
type: 'add',
payload: {
value: file,
canShow: filesToExpand.includes(file.type),
hidden: true
}
}),
remove: id => dispatch({
type: 'remove',
payload: {id: id}
})
};
return (
<FilesContext.Provider value={value}>{children}</FilesContext.Provider>
);
};
const generateId = () => (performance.now().toString(36) +
Math.random().toString(36)).replace(/\./g, '');
export const reducer = (state, action) => {
const payload = action.payload;
switch (action.type) {
case 'add':
return [
...state,
{
id: generateId(),
value: payload.value,
canShow: payload.canShow,
hidden: payload.hidden,
}
];
case 'remove':
return [...state.filter(file => file.id !== payload.id)];
default:
return state;
}
};