class Example extends React.Component {
複製代碼
componentDidMount () {
fetch(`http://my.api/${this.props.name}`)
.then(...)
}
複製代碼
componentDidUpdate (prevProps) {
if (this.props.name !== prevProps.name) {
fetch(`http://my.api/${this.props.name}`)
.then(...)
}
}
}
複製代碼
fetchData () {
fetch(`http://my.api/${this.props.name}`)
.then(...)
}
複製代碼
componentDidMount () {
this.fetchData()
}
componentDidUpdate (prevProps) {
if (this.props.name !== prevProps.name) { this.fetchData()
}
}
複製代碼
import authenticateUser, { AuthenticationContext } from './auth'
複製代碼
const App = () => (
<AuthenticationContext.Consumer>
{user =>
複製代碼
user ? `${user} logged in` : 'not logged in'
複製代碼
}
</AuthenticationContext.Consumer>
)
export default authenticateUser(App)
複製代碼
<AuthenticationContext.Consumer>
{user => (
<LanguageContext.Consumer> {language => ( <StatusContext.Consumer> {status => ( ... )} </StatusContext.Consumer> )} </LanguageContext.Consumer>
)}
</AuthenticationContext.Consumer>
複製代碼
function Example ({ name }) {
useEffect(() => {
fetch(`http://my.api/${this.props.name}`)
.then(...)
}, [ name ])
// ...
}
複製代碼
const user = useContext(AuthenticationContext)
const language = useContext(LanguageContext)
const status = useContext(StatusContext)
複製代碼
import React, { useState } from 'react';
import "./Welcome.scss";
function Welcome() {
const [data, setData] = useState({ hits: [{
objectID:"001",
url:"https://www.jd.com/",
title:"JD"
}] });
return (
<ul> {data.hits.map(item => ( <li key={item.objectID}> <a href={item.url}>{item.title}</a> </li> ))} </ul>
);
}
export default Welcome;
複製代碼
function Welcome() {
const [data, setData] = useState({ hits: [{
objectID:"001",
url:"https://www.jd.com/",
title:"JD"
}] });
useEffect(async () => {
const result = await axios(
'http://localhost/api/v1/search?query=redux'
);
setData(result.data);
});
return (
<ul> {data.hits.map(item => ( <li key={item.objectID}> <a href={item.url}>{item.title}</a> </li> ))} </ul>
);
}
複製代碼
function Welcome() {
const [data, setData] = useState({ hits: [{
objectID:"001",
url:"https://www.jd.com/",
title:"JD"
}] });
useEffect(async () => {
const result = await axios(
'http://localhost/api/v1/search?query=redux'
);
setData(result.data);
},[]);
return (
<ul> {data.hits.map(item => ( <li key={item.objectID}> <a href={item.url}>{item.title}</a> </li> ))} </ul>
);
}
複製代碼
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'http://localhost/api/v1/search?query=redux',
);
setData(result.data);
};
fetchData();
}, []);
複製代碼
loading處理完成後,還須要處理錯誤,這裏的邏輯是同樣的,使用useState來建立一個新的state,而後在useEffect中特定的位置來更新這個state。因爲咱們使用了async/await,可使用一個try-catch, 每次useEffect執行時,將會重置error;在出現錯誤的時候,將error置爲true;在正常請求完成後,將error置爲false。javascript
function Welcome() {
const [data, setData] = useState({ hits: [] });
const [query, setQuery] = useState('redux');
const [url, setUrl] = useState(
'http://localhost/api/v1/search?query=redux',
);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsError(false);
setIsLoading(true);
try {
const result = await axios(url);
setData(result.data);
} catch (error) {
setIsError(true);
}
setIsLoading(false);
};
fetchData();
}, [url]);
}
複製代碼
方法名 | 用法 | 示例 | 思考 |
---|---|---|---|
useRef | 該方法返回一個可變的ref對象,其中.current屬性初始化爲傳遞的參數initialValue | import { useRef } from 'react'; const refContainer = useRef(initialValue) | useRef用於處理對React中的元素和組件的引用。咱們能夠經過將ref屬性傳遞給元素或組件來設置引用。 |
useReducer | 這個是useState的替代方案,其工做方式與Redux庫相似 | import { useReducer } from 'react'; const [ state, dispatch ] = useReducer(reducer, initialArg, init) |
useReducer經常使用於處理複雜的狀態邏輯。 |
useMemo | Memoization是一種優化技術,它緩存函數調用的結果,useMemo容許咱們計算一個值並將其記錄下來 | import { useMemo } from 'react'; const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]) |
當咱們但願避免從新執行費時的操做時,useMemo對於性能優化很是有用。 |
useCallback | 這個方法容許咱們傳遞一個內聯回調函數和一組依賴項,並將返回回調函數的記憶版本。 | import { useCallback } from 'react'; const memoizedCallback = useCallback(() => {doSomething(a, b) }, [a, b]) | 當將回調函數傳遞給子組件時,useCallback很是有用。它的工做方式相似於useMemo,但用於回調函數。 |
useLayoutEffect | useLayoutEffect與useffect相同,但它只在全部的文檔對象模型(Document Object Model,DOM)改變以後才觸發。 | import { useLayoutEffect } from 'react'; useLayoutEffect(didUpdate) | useLayoutEffect可用於從DOM讀取信息。(最好使用useffect,useLayoutEffect將阻止試圖更新並減慢應用程序的渲染速度) |
useDebugValue | useDebugValue可用於在建立自定義Hook時在React DevTools中顯示標籤。 | import { useDebugValue } from 'react'; useDebugValue(value) | 在自定義Hook中可使用useDebugValue來顯示Hook的當前狀態,這樣能夠更容易地調試組件。 |
import { useInput } from 'react-hookedup'
function App () {
const { value, onChange } = useInput('')
return <input value={value} onChange={onChange} />
}
複製代碼
import { useResource } from 'react-request-hook'
const [profile, getProfile] = useResource(id => ({ url: `/user/${id}`,
method: 'GET'
})
複製代碼
import { useCurrentRoute, useNavigation } from 'react-navi'
const { views, url, data, status } = useCurrentRoute()
const { navigate } = useNavigation()
複製代碼
import { useOnMount, useOnUnmount } from 'react-hookedup'
useOnMount(() => { ... })
useOnUnmount(() => { ... })
複製代碼
import { useInterval, useTimeout } from 'react-hookedup'
useInterval(() => { ... }, 1000)
useTimeout(() => { ... }, 1000)
複製代碼
import React from 'react'
import ReactDOM from 'react-dom'
複製代碼
function useState (initialState) {
複製代碼
let value = initialState
複製代碼
function setState (nextValue) {
value = nextValue
ReactDOM.render(<MyName />,
document.getElementById('root'))
}
複製代碼
return [ value, setState ]
}
複製代碼
const [ name, setName ] = useState('')
複製代碼
let value
function useState (initialState) {
複製代碼
if (typeof value === 'undefined') value = initialState
複製代碼
const [ name, setName ] = useState('')
const [ lastName, setLastName ] = useState('')
複製代碼
function handleLastNameChange (evt) {
setLastName(evt.target.value)
}
複製代碼
<h1>My name is: {name} {lastName}</h1>
複製代碼
<input type="text" value={lastName} onChange=
{handleLastNameChange}
/>
複製代碼
let value
複製代碼
let values = []
let currentHook = 0
複製代碼
if (typeof values[currentHook] === 'undefined')
values[currentHook] = initialState
複製代碼
let hookIndex = currentHook
function setState (nextValue) {
values[hookIndex] = nextValue
ReactDOM.render(<MyName />,
document.getElementById('root'))
}
複製代碼
return [ values[currentHook++], setState ]
複製代碼
function Name () {
currentHook = 0
複製代碼
const [ enableFirstName, setEnableFirstName ] = useState(false)
複製代碼
function handleEnableChange (evt) {
setEnableFirstName(!enableFirstName)
}
複製代碼
<input type="checkbox" value={enableFirstName} onChange= {handleEnableChange} />
複製代碼
<h1>My name is: {enableFirstName ? name : ''} {lastName}
</h1>
複製代碼
const [ name, setName ] = enableFirstName ? useState('')
: [ '', () => {} ]
複製代碼
> npm install --save react-scripts@^2.1.8
複製代碼
function UserInfo ({ username }) {
if (username) {
const info = useFetchUserInfo(username)
return <div>{info}</div>
}
return <div>Not logged in</div>
}
複製代碼
function LoggedInUserInfo ({ username }) { const info = useFetchUserInfo(username)
return <div>{info}</div>
}
function UserInfo ({ username }) {
if (username) {
return <LoggedInUserInfo username={username} />
}
return <div>Not logged in</div>
}
複製代碼
function OnlineUsers ({ users }) {
const [ userInfos, setUserInfos ] = useState([])
// ... fetch & keep userInfos up to date ...
return ( <div> {users.map(username => { const user = userInfos.find(u => u.username === username) return <UserInfo {...user} /> })} </div>
)
}
複製代碼
function OnlineUsers ({ users }) {
return (
<div> {users.map(username => <UserInfo username={username} />)} </div>
)
}
function UserInfo ({ username }) {
const info = useFetchUserInfo(username)
// ... keep user info up to date ...
複製代碼
type Hooks = {
memoizedState: any, // 指向當前渲染節點 Fiber
baseState: any, // 初始化 initialState, 已經每次 dispatch 以後 newState
baseUpdate: Update<any> | null,// 當前須要更新的 Update ,每次更新完以後,會賦值上 一個
update,方便 react 在渲染錯誤的邊緣,數據回溯
queue: UpdateQueue<any> | null,// UpdateQueue 經過
next: Hook | null, // link 到下一個 hooks,經過 next 串聯每一 hooks
}
type Effect = {
tag: HookEffectTag, // effectTag 標記當前 hook 做用在 life-cycles 的哪個階段
create: () => mixed, // 初始化 callback
destroy: (() => mixed) | null, // 卸載 callback
deps: Array<mixed> | null,
next: Effect, // 同上
};
複製代碼
class 組件 | Hooks 組件 |
---|---|
constructor | useState |
getDerivedStateFromProps | useState 裏面 update 函數 |
shouldComponentUpdate | useMemo |
render | 函數自己 |
componentDidMount | useEffect |
componentDidUpdate | useEffect |
componentWillUnmount | useEffect 裏面返回的函數 |
componentDidCatch | 無 |
getDerivedStateFromError | 無 |
class 組件 | Hooks 組件 |
---|---|
代碼邏輯清晰(構造函數、componentDidMount等) | 須要配合註釋和變量名 |
不容易內存泄漏 | 容易發生內存泄漏 |
一、官方文檔css
二、useEffect 完整指南html
三、React 高階組件java
四、簡書 React Hooksreact