/public/img/morning.jpg
, то писать надо соответственно '/img/morning.jpg
без всяких assets и наоборот. import { json, useLoaderData } from "react-router-dom";
import { useEffect } from "react";
export function eagerLoader(loader) {
return (...args) => {
const promise = loader(...args)
.then(res => res instanceof Response ? res.json() : res );
return json({ promise }, { status: 200 });
}
}
export function useEagerLoaderData(defaultData) {
const [data, setData] = useState(defaultData);
const promise = useLoaderData()?.promise;
useEffect(() => {
promise?.then(setData);
}, [promise]);
return data;
}
let route = {
path: "...",
loader: eagerLoader(({ request }) => ...),
lazy: () => import("./Comp"),
};
const Comp = () => {
const data = useEagerLoaderData([]);
//...
}
@message-notice-content-bg
, в v5 через свойство contentBg
: .custom-class .ant-message-notice-content { ... }
const [selected, setSelected] = useState('all');
let filterdTodos;
switch(selected) {
case 'all':
filterdTodos = todos;
break;
case 'checked':
filterdTodos = todos.filter(t => t.checked);
break;
case 'notChecked':
filterdTodos = todos.filter(t => !t.checked);
break;
}
const [selected, setSelected] = useState('all');
const filterdTodos = useMemo(() => {
switch(selected) {
case 'all':
return todos;
case 'checked':
return todos.filter(t => t.checked);
case 'notChecked':
return todos.filter(t => !t.checked);
}
}, [selected, todos])
<select className="todos__filter" onChange={(event) =>setSelected(event.target.value)}>
...
{filterdTodos.map(...)}
import img from './assets/img.jpeg'
public
и брать их как есть по прямым путям относительно корня без всяких хэшей.useMemo
нужен, чтобы при передаче значения как prop
в низлежащий memo
компонент не происходила перерисовка оного если не было изменений(+при передаче как зависимость в другой хук, тот не срабатывал заново).useMemo
и пойдёт водопадом перерисовка на каждый чих каждого компонента по всему дереву вниз. И именно это является основной причиной тормозов в React, а не какие-то там мифические сложные вычисления.useMemo
"только в узких местах" и нигде больше. Прикол в том, что с таким подходом при разрастании проекта никакого "узкого места" просто нет, тормозить начинает просто потому, что складываются тысячи микротормозов от тысяч перерисовок тысяч компонентов: наступает то самое "потом" и тут придётся переписывать с useMemo
чуть ли не весь проект, чтоб снизить эти тормоза.useMemo
стараются таки использовать заранее в каждом месте, где оно потенциально нужно. Некоторые радикальные философии вообще предполагают использование useMemo
просто всегда, без исключений.:) const lines = [1, 2, 3];
return lines.map(line => (
<p> {line} </p>
));
function Component() {
const [lines, setLines] = useState([1, 2, 3]);
const addLine = useCallback(() => {
setLines(lines => [...lines, lines.length+1])
});
return(
<>
<button onClick={addLine} className="button">
addLine
</button>
{lines.map(line => (
<p> {line} </p>
))}
</>
}
setTimeout
(тут я обернул его в Promise
для простоты и наглядности):const delay = (ms) => new Promise(r => setTimeout(r, ms))
function Component() {
const [lines, setLines] = useState([]);
const addLines = useCallback(async () => {
let i = 0;
while(i++ < 10) {
await delay(1000);
setLines(lines => [...lines, i])
}
});
return(
<>
<button onClick={addLines} className="button">
addLine
</button>
{lines.map(line => (
<p> {line} </p>
))}
</>
);
}
function useState(initialValue) {
// подсчитываем вызовы useState в компоненте
component.useStateCount++;
// если уже был вызов этого useState(т.е. это не первая отрисовка)
if (component.useStateCount in component.useStateCache)
// возвращаем результат из кэша
return component.useStateCache[component.useStateCount];
// если первый вызов - подготавливаем ответ вида [state, setState]
const useStateResult = [
initialValue,
function setState(callbackOrValue) {
// если аргумент setState - функция
if (typeof callbackOrValue === 'function') {
// вызываем её с предыдущем значением в качестве аргумента и присваиваем результат вызова в state
useStateResult[0] = callbackOrValue(useStateResult[0]);
} else {
// иначе просто присваиваем аргумент в state
useStateResult[0] = callbackOrValue;
}
// вызов обновления компонента
component.updateComounent();
}
];
// добавляем в кэш
component.useStateCache[component.useStateCount] = useStateResult;
// возвращаем
return useStateResult;
}