- https://twitter.com/hillelogram
- https://twitter.com/chatur_shalabh
- https://twitter.com/arkwrite
- https://twitter.com/Wattenberger
- https://twitter.com/ioctaptceb
- https://twitter.com/simonw
- https://twitter.com/redblobgames
- https://twitter.com/andy_matuschak
- https://twitter.com/sebmarkbage
- https://twitter.com/slicknet
View list.md
View CustomEvent.md
Предположим, у меня есть список айтемов, где у каждого, например, есть кнопка удаления. По нажатию на кнопку просто вызывается какая-то функция, которая работает с backend API.
function ListItem({ data }) {
return (
<li className="list-item">
{/* ... */}
<button
View Patterns.md
Data Injection
Задача: компоненту необходимо получить сторонние данные, которые он не может получить через пропсы.
Проблема: разные источники данных могут иметь разные API, которые влекут за
собой необходимость реализации дополнительных аспектов в рамках компонента:
useState
/useEffect
, обработка loading state, доступ к асинхронным API, etc.
Решение: Каждый раз когда компоненту нужны сторонние данные, создавай
View request.js
/* @flow */ | |
/** | |
* @example Simple GET request | |
* let users = await request('/api/users'); | |
* | |
* @example Cancellable GET request | |
* let [result, abort] = request('/api/users', { cancellable: true }); | |
* | |
* @example Simple POST request | |
* let task = await request('/api/tasks', { |
View LoginPage.js
import * as React from 'react'; | |
import { useState } from 'react'; | |
import { useHistory } from 'react-router-dom'; | |
import useAsyncCallback from './useAsyncCallback'; | |
export default function LoginPage() { | |
let history = useHistory(); | |
return ( | |
<article> | |
{/* какой-то контент, всё что угодно на странице логина */} |
View Expansion.md
Представим компонент, написанный какое-то время назад, используется в приложении, работает без проблем
function MyComponent({ input }) {
let [something, setSomething] = useState();
let data = useSomeFetchLibrary(input);
return (
<section>
<ContentA input={something} />
<ContentB input={data} />
View setupProxy.js
let proxy = require('http-proxy-middleware'); | |
module.exports = app => { | |
let backend = proxy({ | |
target: process.env.DATAROBOT_ENDPOINT, | |
changeOrigin: true, | |
}); | |
let socket = proxy('/socket.io-queue', { | |
target: process.env.DATAROBOT_ENDPOINT, | |
changeOrigin: true, |
View aspect-ratio-box.css
/* source: https://css-tricks.com/aspect-ratio-boxes/ */ | |
.aspect-ratio-box { | |
position: relative; | |
} | |
.aspect-ratio-box::before { | |
content: ''; | |
float: left; | |
padding-top: calc(100% / (var(--aspect-ratio))); /* --aspect-ratio: 16 / 9 */ | |
} | |
.aspect-ratio-box::after { |
View DataTable.js
let DataContext = React.createContext(); | |
function DataTable({ children }) { | |
return <section className="data-table">{children}</section>; | |
} | |
function DataTableHead({ children }) { | |
return ( | |
<header className="data-table-head"> | |
<div className="data-table-row">{children}</div> |
View useTransitionState.js
function useTransitionState(ref) { | |
let [pending, setPending] = useState(false); | |
useLayoutEffect(() => { | |
let target = ref.current; | |
let handler = { | |
handleEvent(event) { | |
setPending(event.type === 'transitionstart'); | |
} | |
} | |
target.addEventListener('transitionstart', handler); |
NewerOlder