Введение
React 16.8 был официально выпущен в 2019.2.Это функция, которая может улучшить качество кода и эффективность разработки.Сначала автор перечислит некоторые практические моменты, надеясь получить дальнейшее обсуждение.
Однако следует понимать, что идеальных спецификаций на основе лучших практик не существует, для эффективной команды стабильные спецификации важнее разумных спецификаций, поэтому данное решение является лишь одной из лучших практик.
интенсивное чтение
Требования к окружающей среде
- Иметь относительно стабильную команду фронтенда, которая понимает функциональное программирование.
- Запустите плагин ESLint:eslint-plugin-react-hooks.
определение компонента
Функциональный компонент принимаетconst
+ Определение функции стрелки:
const App: React.FC<{ title: string }> = ({ title }) => {
return React.useMemo(() => <div>{title}</div>, [title]);
};
App.defaultProps = {
title: 'Function Component'
}
Приведенный выше пример содержит:
- использовать
React.FC
Объявите тип компонента Function Component и определите тип параметра Props. - использовать
React.useMemo
Оптимизирована производительность рендеринга. - использовать
App.defaultProps
Определяет значения по умолчанию для реквизита.
FAQ
Почему бы не использовать React.memo?
Рекомендуемое использованиеReact.useMemo
вместоReact.memo
, потому что когда компонент общаетсяReact.useContext
использование, это использование приведет к повторному рендерингу всех используемых компонентов, толькоReact.useMemo
Рендеринг по запросу, который может обрабатывать такие сцены.
Должны ли компоненты без проблем с производительностью также использовать useMemo?
Да, при рассмотрении вопроса о сохранении этого компонента в будущем его можно передать в любое время.useContext
Подождите, пока будут введены некоторые данные, кто подумает добавить их в это времяuseMemo
Шерстяная ткань?
Почему бы не использовать деструктурирование вместо defaultProps?
Хотя деконструированное письмоdefaultProps
Изящнее, но есть недостаток: ссылка на тип объекта будет меняться каждый раз при создании Renderer, что вызовет проблемы с производительностью, так что не делайте этого.
местное государство
Есть три вида локальных состояний, расположенных в порядке общего использования:useState
useRef
useReducer
.
useState
const [hide, setHide] = React.useState(false);
const [name, setName] = React.useState('BI');
Имя функции состояния должно быть выразительным и должно быть максимально собрано вместе, чтобы объявить его для удобства использования.
useRef
const dom = React.useRef(null);
useRef
Используйте как можно меньше, большой объем изменяемых данных повлияет на удобство сопровождения кода.
Но рекомендуется для объектов, которые не нужно повторно инициализироватьuseRef
хранения, напримерnew G2()
.
useReducer
Локальное состояние устарелоuseReducer
, что сделает внутреннее состояние функции слишком сложным и трудным для чтения.useReducer
При обмене данными между несколькими компонентами рекомендуется комбинироватьuseContext
использовать вместе.
FAQ
Можно ли объявить обычную константу или обычную функцию непосредственно внутри функции?
Нет, функциональный компонент будет повторно выполняться каждый раз при его рендеринге. Константы рекомендуется размещать вне функций, чтобы избежать проблем с производительностью. Рекомендуется использовать функции.useCallback
объявить.
функция
Все функции функционального компонента должны использоватьReact.useCallback
упакованы для точности и производительности.
const [hide, setHide] = React.useState(false);
const handleClick = React.useCallback(() => {
setHide(isHide => !isHide)
}, [])
useCallback
Второй параметр должен быть записан,eslint-plugin-react-hooksПлагин автоматически заполняет зависимости.
Отправить запрос
Запросы на отправку делятся на запросы на отправку операционного типа и запросы на отправку типа рендеринга.
запрос действия
Оперативный запрос, как функция обратного вызова:
return React.useMemo(() => {
return (
<div onClick={requestService.addList} />
)
}, [requestService.addList])
сделать запрос
Запрос на рендеринг находится вuseAsync
например, обновление страницы со списком, получение основной информации или поиск,можно абстрагироваться, чтобы зависеть от некоторых переменных, и когда эти переменные изменяются, число необходимо повторно получить:
const { loading, error, value } = useAsync(async () => {
return requestService.freshList(id);
}, [requestService.freshList, id]);
Связь между компонентами
Простая межкомпонентная коммуникация использует метод прозрачной передачи переменных Props, в то время как частая межкомпонентная коммуникация используетReact.useContext
.
Возьмем в качестве примера сложный большой компонент, если компонент разделен на множество модулей,но должен делиться большим количеством внутреннего состояния, лучшая практика заключается в следующем:
Определить общее состояние внутри компонента — store.ts
export const StoreContext = React.createContext<{
state: State;
dispatch: React.Dispatch<Action>;
}>(null)
export interface State {};
export interface Action { type: 'xxx' } | { type: 'yyy' };
export const initState: State = {};
export const reducer: React.Reducer<State, Action> = (state, action) => {
switch (action.type) {
default:
return state;
}
};
Корневой компонент внедряет общее состояние — main.ts
import { StoreContext, reducer, initState } from './store'
const AppProvider: React.FC = props => {
const [state, dispatch] = React.useReducer(reducer, initState);
return React.useMemo(() => (
<StoreContext.Provider value={{ state, dispatch }}>
<App />
</StoreContext.Provider>
), [state, dispatch])
};
Любой дочерний компонент, доступ/изменение общего состояния - child.ts
import { StoreContext } from './store'
const app: React.FC = () => {
const { state, dispatch } = React.useContext(StoreContext);
return React.useMemo(() => (
<div>{state.name}</div>
), [state.name])
};
Решено, как указано вышеПроблема удобного разделения состояния между несколькими тесно связанными компонентами, но иногда также сталкиваются с проблемой необходимости совместного использования Props корневого компонента,Это неизменяемое состояние не подходит для подключения кStoreContext
внутри, мы создаем новыйPropsContext
Реквизиты внедряются в корневой компонент:
const PropsContext = React.createContext<Props>(null)
const AppProvider: React.FC<Props> = props => {
return React.useMemo(() => (
<PropsContext.Provider value={props}>
<App />
</PropsContext.Provider>
), [props])
};
Объединить поток данных проекта
Ссылаться наreact-redux hooks.
оптимизация устранения отказов
Например, когда поле ввода часто используется, чтобы обеспечить плавность страницы, мы выберемonChange
когдаdebounce
. Однако в области функционального компонента у нас есть более элегантный способ сделать это.
Собственно в компоненте Input
onChange
использоватьdebounce
Есть проблема, когда компонент Inputконтролируемый час,debounce
Значение не может быть заполнено вовремя, что приводит к проблеме, что его даже нельзя ввести.
Мы стоим в режиме мышления «Функциональный компонент» и думаем об этой проблеме:
- React schedulingБлагодаря оптимизации приоритета рендеринга с помощью интеллектуальной системы планирования нам не нужно беспокоиться о проблемах с производительностью, вызванных частыми изменениями состояния.
- Вы все еще чувствуете себя медленно, если связываете текст?
onChange
Это не медленно, большинство компонентов, использующих значения, не медленные, нет необходимости начинать сonChange
из источникаdebounce
. - найти компонент с самой низкой производительностью рендеринга (например, компонент iframe),Выполните некоторые входные параметры, которые часто вызывают его рендеринг
useDebounce
.
Ниже представлен плохо работающий компонент, который ссылается на часто меняющиесяtext
(этоtext
может бытьonChange
вызвать изменение), мы используемuseDebounce
Чтобы замедлить частоту его изменений:
const App: React.FC = ({ text }) => {
// 无论 text 变化多快,textDebounce 最多 1 秒修改一次
const textDebounce = useDebounce(text, 1000)
return useMemo(() => {
// 使用 textDebounce,但渲染速度很慢的一堆代码
}, [textDebounce])
};
использоватьtextDebounce
альтернативаtext
Частоту рендеринга можно контролировать в указанном нами диапазоне.
Меры предосторожности
По факту,useEffect
Самый странный хук и самый сложный в использовании. Например следующий код:
useEffect(() => {
props.onChange(props.id)
}, [props.onChange, props.id])
еслиid
изменения, звонитеonChange
. Но если код верхнего уровня неonChange
Разумная инкапсуляция приведет к изменению ссылки при каждом ее обновлении, что будет иметь серьезные последствия. Предположим, что родительский код написан так:
class App {
render() {
return <Child id={this.state.id} onChange={id => this.setState({ id })} />
}
}
Это приведет к бесконечному циклу. Хотя кажется<App>
Просто проведите время, чтобы обновить идентификатор дочернего элемента<Child>
, но из-заonChange
Функция регенерируется при каждом рендеринге, поэтому ссылка всегда меняется, создавая бесконечный цикл:
новыйonChange
-> useEffect
Обновление зависимости ->props.onChange
-> родительский повторный рендеринг -> новыйonChange
...
Чтобы остановить этот цикл, просто измените наonChange={this.handleChange}
Вот и все,useEffect
Строгие требования к внешним зависимостям могут корректно вступить в силу только в том случае, если весь проект позаботится о поддержке правильных ссылок.
Однако то, как написан код в вызываемом объекте, не находится под нашим контролем, что приводит к нестандартным родительским элементам, что может привести к бесконечному циклу React Hooks.
Итак, используяuseEffect
При отладке обратите внимание на контекст отладки и обратите внимание на правильность ссылки на параметр, переданной родителем.Если ссылка передана неправильно, есть два способа:
- использоватьuseDeepCompareEffectСделайте глубокое сравнение зависимостей.
- использовать
useCurrentValue
Оберните реквизиты, ссылки на которые всегда меняются:
function useCurrentValue<T>(value: T): React.RefObject<T> {
const ref = React.useRef(null);
ref.current = value;
return ref;
}
const App: React.FC = ({ onChange }) => {
const onChangeCurrent = useCurrentValue(onChange)
};
onChangeCurrent
ссылка остается прежней, но каждый раз указывает на последнююprops.onChange
, чтобы избежать этой проблемы.
Суммировать
Если есть какие-то дополнения, милости просим обсудить в конце статьи.
Если вы хотите понять основы использования функционального компонента или хуков, вы можете обратиться к предыдущему интенсивному чтению:
- Интенсивное чтение «React Hooks»
- Интенсивное чтение "Как использовать React Hooks для сборки колеса"
- Прочтите полное руководство по использованию эффектов
- Интенсивное чтение «Введение в функциональный компонент»
Адрес обсуждения:Интенсивное чтение «React Hooks Best Practices», выпуск № 202 dt-fe/еженедельно
Если вы хотите принять участие в обсуждении, пожалуйста,кликните сюда, с новыми темами каждую неделю, выходящими по выходным или понедельникам. Интерфейс интенсивного чтения — поможет вам отфильтровать надежный контент.
обрати внимание наАккаунт WeChat для интенсивного чтения в интерфейсе
Заявление об авторских правах: Бесплатная перепечатка - некоммерческая - не производная - сохранить авторство (Лицензия Creative Commons 3.0)