@@ -4541,24 +4596,24 @@
```jsx
class Counter extends Component {
state = { value: 0 };
-
+
handleIncrement = () => {
this.setState(prevState => ({
value: prevState.value + 1
}));
};
-
+
handleDecrement = () => {
this.setState(prevState => ({
value: prevState.value - 1
}));
};
-
+
render() {
return (
@@ -4575,11 +4630,11 @@
```jsx
import { useState } from 'react';
-
+
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
-
+
return (
You clicked {count} times
@@ -4592,7 +4647,7 @@
```
阅读资源:
-
+
1. [掘金 - 30分钟精通React Hooks](https://juejin.im/post/5be3ea136fb9a049f9121014)
**[⬆ 返回顶部](#目录)**
@@ -4696,7 +4751,7 @@
super(props);
this.state = { error: null };
}
-
+
handleClick = () => {
try {
// Do something that could throw
@@ -4704,7 +4759,7 @@
this.setState({ error });
}
}
-
+
render() {
if (this.state.error) {
return
Caught an error.
@@ -4819,11 +4874,11 @@
class MyButton extends React.Component {
// ...
}
-
+
MyButton.defaultProps = {
color: 'red'
};
-
+
```
如果未设置 props.color,则会使用默认值 `red`。 也就是说,每当你试图访问 color 属性时,它都使用默认值。
@@ -4860,18 +4915,18 @@
super(props);
this.state = { hasError: false };
}
-
+
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
-
+
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return
Something went wrong.
;
}
-
+
return this.props.children;
}
}
@@ -4903,7 +4958,7 @@
247. ### displayName 类属性的用途是什么?
displayName 被用于调试信息。通常,你不需要显式设置它,因为它是从定义组件的函数或类的名称推断出来的。如果出于调试目的或在创建高阶组件时显示不同的名称,可能需要显式设置它。
-
+
例如,若要简化调试,请选择一个显示名称,以表明它是 withSubscription HOC 的结果。
```javascript
@@ -4912,7 +4967,7 @@
WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;
return WithSubscription;
}
-
+
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
@@ -4943,13 +4998,13 @@
**moduleA.js**
```javascript
const moduleA = 'Hello';
-
+
export { moduleA };
```
**App.js**
```javascript
import React, { Component } from 'react';
-
+
class App extends Component {
handleClick = () => {
import('./moduleA')
@@ -4960,7 +5015,7 @@
// Handle failure
});
};
-
+
render() {
return (
@@ -4969,7 +5024,7 @@
);
}
}
-
+
export default App;
```
@@ -5093,16 +5148,16 @@
class LogProps extends React.Component {
// ...
}
-
+
function forwardRef(props, ref) {
return
;
}
-
+
// Give this component a more helpful display name in DevTools.
// e.g. "ForwardRef(logProps(MyComponent))"
const name = Component.displayName || Component.name;
forwardRef.displayName = `logProps(${name})`;
-
+
return React.forwardRef(forwardRef);
}
```
@@ -5115,7 +5170,7 @@
```javascript
-
+
```
@@ -5168,14 +5223,14 @@
260. ### 如何防止函数被多次调用?
如果你使用一个事件处理程序,如 **onClick or onScroll** 并希望防止回调被过快地触发,那么你可以限制回调的执行速度。
-
+
这可以通过以下可能的方式实现:
1. **Throttling:** 基于时间的频率进行更改。例如,它可以使用 lodash 的 _.throttle 函数。
2. **Debouncing:** 在一段时间不活动后发布更改。例如,可以使用 lodash 的 _.debounce 函数。
3. **RequestAnimationFrame throttling:** 基于 requestAnimationFrame 的更改。例如,可以使用 raf-schd。
- > 注意:_.debounce , _.throttle 和 raf-schd 都提供了一个 cancel 方法来取消延迟回调。所以需要调用 componentWillUnmount,或者对代码进行检查来保证在延迟函数有效期间内组件始终挂载。
+ > 注意:_.debounce, _.throttle 和 raf-schd 都提供了一个 cancel 方法来取消延迟回调。所以需要调用 componentWillUnmount,或者对代码进行检查来保证在延迟函数有效期间内组件始终挂载。
**[⬆ 返回顶部](#目录)**
@@ -5206,7 +5261,7 @@
);
ReactDOM.render(element, document.getElementById('root'));
}
-
+
setInterval(tick, 1000);
```
@@ -5222,13 +5277,12 @@
}
```
- 上面的函数称为 "pure" 函数,因为它不会尝试更改输入,并总是为相同的输入返回相同的结果。因此,React 有一条规则,即"所有 React 组件的行为都必须像纯函数一样。"
+ 上面的函数称为“纯”函数,因为它不会尝试更改输入,并总是为相同的输入返回相同的结果。因此,React 有一条规则,即“所有 React 组件的行为都必须像纯函数一样”。
**[⬆ 返回顶部](#目录)**
264. ### 你认为状态更新是如何合并的?
- When you call setState() in the component, React merges the object you provide into the current state. For example, let us take a facebook user with posts and comments details as state variables,
当你在组件中调用 setState() 方法时,React 会将提供的对象合并到当前状态。例如,让我们以一个使用帖子和评论详细信息的作为状态变量的 Facebook 用户为例:
```javascript
@@ -5250,7 +5304,7 @@
posts: response.posts
});
});
-
+
fetchComments().then(response => {
this.setState({
comments: response.comments
@@ -5285,7 +5339,7 @@
if (!props.loggedIn) {
return null;
}
-
+
return (
welcome, {props.name}
@@ -5300,7 +5354,7 @@
super(props);
this.state = {loggedIn: false, name: 'John'};
}
-
+
render() {
return (
@@ -5396,7 +5450,7 @@
import React, { Component } from 'react';
import './App.css';
import '@vaadin/vaadin-date-picker';
-
+
class App extends Component {
render() {
return (
@@ -5406,7 +5460,7 @@
);
}
}
-
+
export default App;
```
@@ -5437,9 +5491,9 @@
```javascript
import loadable from '@loadable/component'
-
+
const OtherComponent = loadable(() => import('./OtherComponent'))
-
+
function MyComponent() {
return (
@@ -5459,7 +5513,7 @@
```javascript
const OtherComponent = React.lazy(() => import('./OtherComponent'));
-
+
function MyComponent() {
return (
@@ -5482,10 +5536,10 @@
```javascript
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';
-
+
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
-
+
const App = () => (
Loading...
}>
@@ -5543,7 +5597,7 @@
当在组件树中的组件没有匹配到在其上方的 Provider 时,才会使用 defaultValue 参数。这有助于在不包装组件的情况下单独测试组件。下面的代码段提供了默认的主题值 Luna。
```javascript
- const defaultTheme = "Luna";
+ const defaultTheme = "Luna";
const MyContext = React.createContext(defaultTheme);
```
@@ -5622,7 +5676,7 @@
}
}
```
-
+
可以通过把 value 的值提升到父状态中来解决这个问题:
```javascript
@@ -5633,7 +5687,7 @@
value: {something: 'something'},
};
}
-
+
render() {
return (
@@ -5659,15 +5713,15 @@
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
-
+
render() {
const {forwardedRef, ...rest} = this.props;
-
+
// Assign the custom prop "forwardedRef" as a ref
return ;
}
}
-
+
return React.forwardRef((props, ref) => {
return ;
});
@@ -5681,7 +5735,7 @@
focus() {
// ...
}
-
+
// ...
}
export default logProps(FancyButton);
@@ -5691,7 +5745,7 @@
```javascript
import FancyButton from './FancyButton';
-
+
const ref = React.createRef();
ref.current.focus();
Hello {this.props.message};
}
}
-
+
ReactDOM.render(
,
document.getElementById('root')
@@ -5767,7 +5821,7 @@
return React.createElement('div', null, `Hello ${this.props.message}`);
}
}
-
+
ReactDOM.render(
React.createElement(Greeting, {message: 'World'}, null),
document.getElementById('root')
@@ -5830,7 +5884,7 @@
Duke
Villanova
-
+
- Connecticut
- Duke
@@ -5859,7 +5913,7 @@
The mouse position is {mouse.x}, {mouse.y}
)}/>
```
-
+
实际上,以上的 children 属性不一定需要在 JSX 元素的 `attributes` 列表中命名。反之,你可以将它直接放在元素内部:
```javascript
@@ -5888,7 +5942,7 @@
292. ### 如何使用渲染属性创建 HOC?
- 可以使用带有渲染属性的常规组件实现大多数高阶组件(HOC)。例如,如果希望使用 withMouse HOC 而不是 组件,则你可以使用带有渲染属性的常规 组件轻松创建一个 HOC 组件。
+ 可以使用带有渲染属性的常规组件实现大多数高阶组件(HOC)。例如,如果希望使用 withMouse HOC 而不是 `` 组件,则你可以使用带有渲染属性的常规 `` 组件轻松创建一个 HOC 组件。
```javascript
function withMouse(Component) {
@@ -6015,4 +6069,55 @@
React 对如何定义样式没有任何意见,但如果你是初学者,那么好的起点是像往常一样在单独的 *.css 文件中定义样式,并使用类名引用它们。此功能不是 React 的一部分,而是来自第三方库。但是如果你想尝试不同的方法(JS中的CSS),那么 styled-components 库是一个不错的选择。
- **[⬆ 返回顶部](#目录)**
\ No newline at end of file
+ **[⬆ 返回顶部](#目录)**
+
+302. ### 我需要用 hooks 重写所有类组件吗?
+
+ 不需要。但你可以在某些组件(或新组件)中尝试使用 hooks,而无需重写任何已存在的代码。因为在 ReactJS 中目前没有移除 classes 的计划。
+
+ **[⬆ 返回顶部](#目录)**
+
+303. ### 如何使用 React Hooks 获取数据?
+
+ 名为 useEffect 的 effect hook 可用于使用 axios 从 API 中获取数据,并使用 useState 钩子提供的更新函数设置组件本地状态中的数据。让我们举一个例子,它从 API 中获取 react 文章列表。
+
+ ```jsx
+ import React, { useState, useEffect } from 'react';
+ import axios from 'axios';
+
+ function App() {
+ const [data, setData] = useState({ hits: [] });
+
+ useEffect(async () => {
+ const result = await axios(
+ 'http://hn.algolia.com/api/v1/search?query=react',
+ );
+
+ setData(result.data);
+ }, []);
+
+ return (
+
+ );
+ }
+
+ export default App;
+ ```
+
+ 记住,我们为 effect hook 提供了一个空数组作为第二个参数,以避免在组件更新时再次激活它,它只会在组件挂载时被执行。比如,示例中仅在组件挂载时获取数据。
+
+ **[⬆ 返回顶部](#目录)**
+
+304. ### Hooks 是否涵盖了类的所有用例?
+
+ Hooks 并没有涵盖类的所有用例,但是有计划很快添加它们。目前,还没有与不常见的 getSnapshotBeforeUpdate 和componentDidCatch 生命周期等效的钩子。
+
+
+**[⬆ 返回顶部](#目录)**
+
diff --git a/images/fer_road_qrcode.jpg b/images/fer_road_qrcode.jpg
new file mode 100644
index 0000000..ccfb3dc
Binary files /dev/null and b/images/fer_road_qrcode.jpg differ
diff --git a/images/frontend-advanced-intro-v1.1.jpg b/images/frontend-advanced-intro-v1.1.jpg
new file mode 100644
index 0000000..cb01e93
Binary files /dev/null and b/images/frontend-advanced-intro-v1.1.jpg differ