Короткие и полезные заметки про React
export const protectedProcedure = t.procedure.use(isAuthed);
export const appRouter = router({
createPost: protectedProcedure.mutation(({ctx}) => {
const session = ctx.session;
// [...]
}),
});
https://trpc.io/blog/announcing-trpc-10
function Draggable() {
let { dragProps, isDragging } = useDrag({
getItems() {
return [{
'text/plain': 'hello world'
}];
}
});
return (
<div
{...dragProps}
role="button"
tabIndex={0}
className={`draggable ${isDragging ? 'dragging' : ''}`}
>
Drag me
</div>
);
}
react-spectrum.adobe.com/blog/dr…rop.html
export default function Motion() {
const squareRef = React.useRef();
const initialPositionRef = React.useRef();
React.useLayoutEffect(() => {
const box = squareRef.current?.getBoundingClientRect();
if (moved(initialPositionRef.current, box)) {
const deltaX = initialPositionRef.current.x - box.x;
const deltaY = initialPositionRef.current.y - box.y;
squareRef.current.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
// animate back to the final position
animate({
…params,
onUpdate: progress => {
squareRef.current.style.transform =
translate(${deltaX * progress}px, ${deltaY * progress}px);
}
})
}
initialPositionRef.current = box;
});
return <div id="motion" ref={squareRef} />;
}
https://www.nan.fyi/magic-motion
import { AutoForm } from "uniforms"
import { createBridge } from "./createBridge" // explained later
function AutomaticForm() {
return <AutoForm schema={createBridge(loginSchema)} />;
}
https://uniforms.tools/
Гайд www.vazco.eu/blog/a-…ng-formssuspense: true в настройки запроса. При использовании данного механизма нужно быть осторожным. Если у вас несколько запросов в одном компоненте, то возникает проблема “водопада” запросов. При рендере компонента React Query сообщает, что необходимо выполнить первый запрос, React ставит компонент на паузу и ждет выполнения. После успешного выполнения запроса, компонент перемонтируется заново и React Query сообщает, что необходимо выполнить второй запрос, и сценарий повторяется. Так возникает “водопад” запросов.
Чтобы избежать подобных проблем, Доминик Дорфмайстер в своем блоге поделился способами предварительного заполнения кэша для запросов.
Во-первых, предварительно загружайте данные до рендера компонента. Если проект поддерживает SSR, то загружайте данные на сервере. Если роутер поддерживает лоадеры, то загружайте в лоадерах.
const issuesQuery = { queryKey: ['issues'], queryFn: fetchIssues }
queryClient.prefetchQuery(issuesQuery)
function Issues() {
const issues = useQuery(issuesQuery)
}
Во-вторых, если у вас данные в списке и нужен отдельный элемент из списка, то его можно получить из кэша:
const data = useQuery({
queryKey: ['todos', 'detail', id],
queryFn: () => fetchTodo(id),
initialData: () => {
return queryClient
.getQueryData(['todos', 'list'])
?.find((todo) => todo.id === id)
},
})
Другой подход – создавать кэш для отдельного элемента после получения данных для списка:
const data = useQuery({
queryKey: ['todos', 'list'],
queryFn: async () => {
const todos = await fetchTodos()
todos.forEach((todo) => {
queryClient.setQueryData(['todos', 'detail', todo.id], todo)
})
return todos
},
})
Минус такого подхода в том, что данные могут устареть до момента, когда они понадобятся, либо эти данные могут вообще не понадобиться.
https://tkdodo.eu/blog/seeding-the-query-cache@react-three/postprocessing.
vercel.com/blog/bu…-next-js
const useSelector = <STATE,>(
store: {state: STATE; subscribe: any},
selector: (state: STATE) => any,
) => {
const [selectedValue, setSelectedValue]
= useState(selector(store.state))
useEffect(() => {
return store.subscribe(newState => {
setSelectedValue(
selector(newState);
);
});
}, []);
return selectedValue;
}
judehunter.dev/blog/ho…-library/app. В ней можно использовать новые фичи, о которых давно говорили в React.
Layouts.
Позволяет использовать шаблоны для нескольких компонентов. Реализуется через создание файла layout.js.
Server Components.
Next.js начал поддерживать серверные компоненты. Согласно документации все компоненты внутри директории /app являются серверными компонентами по умолчанию. Чтобы обозначить, что компонент является клиентским, нужно в начале файла объявить директиву 'use client';.
Streaming.
Возможность прогрессивного рендера компонентов на странице.
Поддержка async компонентов.
Означает поддержку недавнего RFC о загрузке данных.
Также на конференции рассказали про новый бандлер и сборщик приложения Turbopack. Написан он на Rust, а его главный разработчик – Тобиас Копперс, создатель Webpack. По информации от авторов, Turbopack в 700 раз быстрее Webpack и как минимум в 10 раз быстрее чем Vite. Пока что бандлер находится в альфа-версии.
https://nextjs.org/blog/next-13