Как вернуть массив из пользовательского хука?
Использую реакт. Получаю с сервера массив и отображаю его как таблицу с пагинацией и сортировкой. Пагинацию и сортировку сделал в виде пользовательских хуков, они работают так как нужно. Но при первом рендере массив возвращаемый из функции сортировки куда-то девается, я так решил потому что таблица пустая, потом когда я меняю сортировку таблица заполняется в соответствии с сортировкой.
App.js:
const [items, setItems] = useState([]);
const {setMask, setCurrentColumn, setCurrentCondition, sortedItems} = useSort(items);
const {setCurrentPage, currentItems, amountOfPages} = usePagination(sortedItems);
const [isLoaded, setIsLoaded] = useState(false);
мой хук:
export const useSort = (filteredItems) => {
const [sortedItems, setSortedItems] = useState(filteredItems);
const [mask, setMask] = useState("");
const [currentColumn, setCurrentColumn] = useState("Distance");
const [currentCondition, setCurrentCondition] = useState("greater");
useEffect(() => {
SortQuantity(currentCondition, currentColumn);
SortDistance(currentCondition, currentColumn);
SortName(currentCondition, currentColumn);
}, [currentCondition, currentColumn, mask]);
function SortQuantity (currentCondition, currentColumn) {
if (currentColumn === "Quantity" && currentCondition === "less") {
console.log(mask, currentCondition, currentColumn);
setSortedItems(
filteredItems.filter(item => item.Quantity < mask)
)
} else if (currentColumn === "Quantity" && currentCondition === "greater") {
console.log(mask, currentCondition, currentColumn);
setSortedItems(
filteredItems.filter(item => item.Quantity > mask)
)
} else if (currentColumn === "Quantity" && currentCondition === "equal") {
console.log(mask, currentCondition, currentColumn);
setSortedItems(
filteredItems.filter(item => item.Quantity.toString() === mask)
)
} else return sortedItems
}
function SortDistance (currentCondition, currentColumn) {
if (currentColumn === "Distance" && currentCondition === "less") {
console.log(mask, currentCondition, currentColumn);
setSortedItems(
filteredItems.filter(item => item.Distance < mask)
)
} else if (currentColumn === "Distance" && currentCondition === "greater") {
console.log(mask, currentCondition, currentColumn);
setSortedItems(
filteredItems.filter(item => item.Distance > mask)
)
} else if (currentColumn === "Distance" && currentCondition === "equal") {
console.log(mask, currentCondition, currentColumn);
setSortedItems(
filteredItems.filter(item => item.Distance.toString() === mask)
)
} else return sortedItems
}
function SortName (currentCondition, currentColumn) {
if (currentColumn === "Name" && currentCondition === "contains") {
console.log(mask, currentCondition, currentColumn);
setSortedItems(
filteredItems.filter(item =>
item.Name.toLowerCase().includes(mask.toLowerCase())
)
)
} else return sortedItems
}
return {
setMask,
setCurrentColumn,
setCurrentCondition,
sortedItems
}
};
Ответы (2 шт):
- фильтрованые строки не стейт, а мемо
- эффект не нужен
- функции, вызываемые из
use*: или за пределы компонента, или в вызывающийuse*или вuseCallback - useFilter можно сделать короче и использовать несколько раз
const useFilter = (items, column, filterOperation, filterValue) => {
const filteredItems = useMemo(()=>{
const check =
....
return items.filter(check)
},[items, column, filterOperation, filterValue])
return filteredItems
}
Я решил проблему с первым рендером, теперь всё нормально. Я добавил setSortedItems в фетч - запрос. Как бы оно теперь работает нормально но я понимаю что это костыль и хотелось бы понять почему useEffect не реагировал на массив зависимостей так как я ожидал. Да я понял что надо использовать useMemo, и я использовал, но с ним такая же ситуация.
async function FetchData() {
try {
const response = await fetch('http://localhost:4000/items');
const json = await response.json();
setItems(json);
setIsLoaded(true);
setSortedItems(json);
console.log(json);
} catch (e) {
console.log(e)
}
};