Искренне благодарен, что Вик щедро поделился этой статьей несколько недель назад, и я, наконец, решил погрузиться в нее сегодня во время лихорадочного тайфуна. Статья выходит за рамки простых заметок, она служит демонстрацией того, как я научился эффективно читать с помощью ChatGPT. Если это действительно поможет вам, я был бы очень признателен за палец вверх!
Шаг 1: получите схему/диаграмму
Posts 25 MAY 2023 | | _______________________________________________________ | | Introduction A brief history of React APIs | | | | _______________________________________________________________ | | | | | | Mixins | Higher-order | Render props | Hooks | | | components | | | |________________________________|_______________|_______________| | | | | | | | | ____________|_______ | | | | | | | | Principles behind Tradeoffs Example Evolution | | React's evolution of HOCs of Hooks | | | | | Understanding a Tradeoffs full-stack React
Шаг 2: получить ключевые моменты и примеры (квадратная зона на диаграмме)
Краткая история API React
- Недостатки примесей: коллизия имен и неявные зависимости затрудняли управление в большой кодовой базе.
// Mixin 1: Define a theme mixin with styles for the button. const themeMixin = { styles: { color: 'blue', fontSize: '16px', }, }; // Mixin 2: Define a hover mixin with styles for the button. const hoverMixin = { styles: { backgroundColor: 'yellow', }, }; // Component using mixins class Button extends React.Component { state = { buttonText: 'Click Me', }; render() { const { buttonText } = this.state; // Apply styles from both mixins to the button. // However, a name collision occurs with the "styles" property. // The hoverMixin styles overwrite the themeMixin styles, // leading to unexpected behavior in the button's appearance. return ( <button style={{ ...themeMixin.styles, ...hoverMixin.styles, }} > {buttonText} </button> ); } }
2. Компоненты высшего порядка (HOC): стало проще обеспечивать общее поведение для нескольких компонентов, но конфликты имен и сложные иерархии компонентов, такие как переопределение состояния, неожиданные побочные эффекты и трудная отладка, остаются проблемами.
// Higher Order Component (HOC) to add hover functionality to components const withHover = (Component) => { return class extends React.Component { state = { isHovered: false, }; handleMouseEnter = () => { this.setState({ isHovered: true }); }; handleMouseLeave = () => { this.setState({ isHovered: false }); }; render() { const { isHovered } = this.state; // Wrap the original component with hover behavior return ( <div onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} > <Component isHovered={isHovered} {...this.props} /> </div> ); } }; }; // Higher Order Component (HOC) to add click functionality to components const withClick = (Component) => { return class extends React.Component { state = { isClicked: false, }; handleClick = () => { this.setState({ isClicked: true }); }; render() { const { isClicked } = this.state; // Wrap the original component with click behavior return ( <div onClick={this.handleClick}> <Component isClicked={isClicked} {...this.props} /> </div> ); } }; }; // Component using both hover and click HOCs class Button extends React.Component { render() { const { isHovered, isClicked } = this.props; return ( <button style={{ background: isHovered ? 'yellow' : 'blue', color: isClicked ? 'red' : 'white', }} > Click Me </button> ); } } // Usage of nested HOCs const ButtonWithHoverAndClick = withClick(withHover(Button)); // In the render function of the main component return <ButtonWithHoverAndClick />;
3. Реквизиты рендеринга: обеспечивают более явный поток данных и избегают конфликтов имен, которые были обычными в двух предыдущих. Но, да, но неуклюжий аспект заключается в том, что они могут привести к глубоко вложенным пирамидам.
<Motion style={{ x: 10 }}> {interpolatingStyle => <div style={interpolatingStyle} />} </Motion>
4.Хуки: позволяют совместно размещать состояния и эффекты, упрощая кодовую базу и уменьшая вложенность.
function Example() { const [count, setCount] = useState(0); useEffect(() => { console.log('Component mounted'); }, []); return ( <div> <button onClick={() => setCount(count + 1)}>Click Me</button> <p>Count: {count}</p> </div> ); }
Шаг 3: Разделите ключи на части
Разделение между классами и функциями
Часть 1. Переход от классов к функциям в React: он создает эффект разделения мозга, жонглируя ООП и функциональным программированием.
Часть 2. Компоненты Класс и функция:
- класс использует "this" для состояния и свойств, а функция: закрытие и декларативную синхронизацию.
- В функциональном программировании чистые функциине должны иметь внутреннее состояние или побочные эффекты, но в React управление состоянием необходимо для создания интерактивных пользовательских интерфейсов.
Часть 3. Проблемы построения точной ментальной модели
Опыт разработки
- Переход от классов к функциям и хукам повлиял на опыт.
- Классы имели сложную терминологию и методы привязки, а функции и хуки были упрощены, но требовали явной обработки данных.
- Функция React «забыть» автоматизирует предварительную компиляцию компонентов, чтобы улучшить опыт разработчиков.
Связывание состояния и логики с React
- Ориентация на приложения и компоненты: различные способы управления состоянием в React. App использует глобальные хранилища, такие как Redux, в то время как Component использует хуки, такие как
useState
для состояния внутри компонентов. - Глобальные монолитные хранилища: управление состоянием с помощью централизованных решений, таких как Redux или MobX. Может привести к сложным кодовым базам.
- Совместное размещение с хуками: размещение состояния и логики непосредственно внутри компонентов с помощью хуков. Улучшает организацию кода и аргументацию.
- Переход от отдельного состояния и представления: переход от отдельного состояния и представления к более тесному взаимодействию в компонентах React.
- Улучшение локального мышления и переносимости: перехватчики и состояние совместного размещения улучшают понимание и позволяют повторно использовать компоненты.
// Global monolithic store example const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case 'INCREMENT': return { ...state, count: state.count + 1 }; case 'DECREMENT': return { ...state, count: state.count - 1 }; default: return state; } } const App = () => { const [state, dispatch] = React.useReducer(reducer, initialState); return ( <div> <h1>Count: {state.count}</h1> <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button> <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button> </div> ); } // Component-centric approach with hooks const Counter = () => { const [count, setCount] = React.useState(0); const handleIncrement = () => setCount(count + 1); const handleDecrement = () => setCount(count - 1); return ( <div> <h1>Count: {count}</h1> <button onClick={handleIncrement}>Increment</button> <button onClick={handleDecrement}>Decrement</button> </div> ); } const App = () => { return ( <div> <Counter /> </div> ); }
Шаг 4: получить заключение с заголовком и ключами
Принципы эволюции React
- Взаимодействие пользователей с API: баланс между конечными пользователями и разработчиками. React отдает приоритет пользовательскому опыту, предоставляя гибкий API.
- API важнее реализаций. Концепция высокоуровневого API «компонента» остается стабильной, несмотря на изменения внутренней реализации.
- Сосредоточьтесь на правильных примитивах. Построение на прочной основе с помощью компонентной модели обеспечивает лучшую компоновку и переносимость.
- Переносимость и совместное размещение. Компоненты фиксируют совместное размещение задач, упрощая поддержку и отладку кода.
- Переход от классов к хукам: переход от логики на основе классов к компонуемым функциям внутри компонентов.
и более…
Шаг 5: Для сравнения используйте табличную форму
Понимание полного стека React
| Directive | Purpose | Usage | |----------------|--------------------------------------|-------------------------------------------------------| | "use client" | Marks client-specific code | Placed at the top of a file to indicate client code | | | | Modules are considered part of the client bundle | | | | Components with "use client" can run on the server | | | | Used for generating initial HTML or static site gen. | |----------------|--------------------------------------|-------------------------------------------------------| | "use server" | Used in server components for RPC | Placed at the top of an action function | | | (Remote Procedure Call) | Tells the compiler to keep it on the server | | | | Not included in the client bundle | |----------------|--------------------------------------|-------------------------------------------------------| | "server-only" | Marks code for server-only use | Ensures code is only used on server | | | | Helps prevent accidentally sending client code | | | | Used to mark boundaries in shared module graph | |----------------|--------------------------------------|-------------------------------------------------------|