import React, { useContext } from 'react'
import { ThemeContext } from '../App'
interface IHelloProps {
message?: string;
}
const Hello: React.FC = (props) => {
const theme = useContext(ThemeContext)
console.log(theme)
const style = {
background: theme.background,
color: theme.color,
}
return {props.message}
}
Hello.defaultProps = {
message: "Hello World"
}
export default Hello
钩子是允许从功能组件(function component)“挂钩”React状态和生命周期功能的功能。钩子在类内部不起作用 - 它们允许你在没有类的情况下使用React。
useState简单实例
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
);
}
Effect Hook中的useEffect增加了在功能组件执行副作用的功能。它与React类中的componentDidMount,componentDidUpdate和componentWillUnmount具有相同的用途,但统一为单个API。
简单实例:
import React, { useState, useEffect } from 'react'
const MouseTracker: React.FC = () => {
const [ positions, setPositions ] = useState({x: 0, y: 0})
useEffect(() => {
console.log('add effect', positions.x)
const updateMouse= (e: MouseEvent) => {
console.log('inner')
setPositions({ x: e.clientX, y: e.clientY })
}
document.addEventListener('click', updateMouse)
return () => {
console.log('remove effect', positions.x)
document.removeEventListener('click', updateMouse)
}
}, [])
console.log('before render', positions.x)
return (
X: {positions.x}, Y : {positions.y}
)
}
export default MouseTracker
useEffect不过不传递第二个参数在页面每次重新渲染时都会调用,这里第二个参数传入空数组的意思是只有在页面出现或者卸载时执行.如果传入其他变量则执行与否只依赖该变量是否变化.
不同组件之间共享hook封装
import React, { useState, useEffect } from 'react'
const useMousePosition = () => {
const [ positions, setPositions ] = useState({x: 0, y: 0})
useEffect(() => {
console.log('add effect', positions.x)
const updateMouse= (e: MouseEvent) => {
setPositions({ x: e.clientX, y: e.clientY })
}
document.addEventListener('mousemove', updateMouse)
return () => {
console.log('remove effect', positions.x)
document.removeEventListener('mousemove', updateMouse)
}
}, [])
return positions
}
export default useMousePosition
定义后在其他组件中引入就可共用状态
const positons = useMousePosition();
自定义hook
在react hook中我们可以把一些天然逻辑重复的业务抽离出来,下面看下例子:
定义文件useURLLoader.tsx
import { useState, useEffect } from 'react'
import axios from 'axios'
const useURLLoader = (url: string, deps: any[] = []) => {
const [data, setData] = useState(null)
const [loading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
axios.get(url).then(result => {
setData(result.data)
setLoading(false)
})
}, deps)
return [data, loading]
}
export default useURLLoader
使用
interface IShowResult {
message: string;
status: string;
}
const App: React.FC = () => {
const [show, setShow] = userState(true)
const [data, loadin] = userState(true) = useURLLoader('https://dog.ceo/api/breeds/imagte', show)
const dogResult = data as IShowResult
return (
{loading ? 读取中
: }
)
}
App.tsx文件
import React, { useState } from 'react';
import './App.css';
import LikeButton from './components/LikeButton'
interface IThemeProps {
[key: string]: {color: string; background: string;}
}
const themes: IThemeProps = {
'light': {
color: '#000',
background: '#eee',
},
'dark': {
color: '#fff',
background: '#222',
}
}
export const ThemeContext = React.createContext(themes.light)
const App: React.FC = () => {
const [ show, setShow ] = useState(true)
return (
);
}
export default App;
LikeButton.tsx文件
import React, { useState, useEffect, useRef, useContext } from 'react'
import { ThemeContext } from '../App'
const LikeButton: React.FC = () => {
const [like, setLike] = useState(0)
const likeRef = useRef(0)
const didMountRef = useRef(false)
const domRef = useRef(null)
const theme = useContext(ThemeContext)
console.log(theme)
const style = {
background: theme.background,
color: theme.color,
}
useEffect(() => {
console.log('document title effect is running')
document.title = `点击了${like}次`
}, [like])
useEffect(() => {
if (didMountRef.current) {
console.log('this is updated')
} else {
didMountRef.current = true
}
})
useEffect(() => {
if (domRef && domRef.current) {
domRef.current.focus()
}
})
function handleAlertClick() {
setTimeout(() => {
alert('you clicked on ' + likeRef.current)
}, 3000)
}
return (
<>
>
)
}
export default LikeButton
引用传递(Ref forwading)是一种通过组件向子组件自动传递 引用ref 的技术。
import React, { Component, createRef, forwardRef } from 'react';
const FocusInput = forwardRef((props, ref) => (
));
class ForwardRef extends Component {
constructor(props) {
super(props);
this.ref = createRef();
}
componentDidMount() {
const { current } = this.ref;
current.focus();
}
render() {
return (
forward ref
);
}
}
export default ForwardRef;
const refContainer = useRef(initialValue);
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内持续存在。
一个常见的用例便是命令式地访问子组件:
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
>
);
}
useRef和createRef的区别
import { useRequest } from '@umijs/hooks';
function getUsername() {
return Promise.resolve('jack');
}
export default () => {
const { data, error, loading } = useRequest(getUsername)
if (error) return failed to load
if (loading) return loading...
return Username: {data}
}
这是一个最简单的网络请求示例。在这个例子中 useRequest 接收了一个 Promise 函数。在组件初始化时,会自动触发 getUsername 执行,并自动管理 data 、 loading 、 error 等数据,我们只需要根据状态来写相应的 UI 实现即可。
useRequest教程
1、确定输入输出,useCreation接受两个参数,一个工厂函数,一个依赖项数组,并返回工厂函数执行后的结果
一篇文章带你理解 React 中最“臭名昭著”的 useMemo 和 useCallback
参考
父组件
import { useCallback, useEffect, useState, useRef } from "react";
import Header from "../../components/header/index";
import Footer from "../../components/footer/index";
import Changefather from "./components/changefather";
const Home = () => {
const [sisters, setsisters] = useState("村里一朵花");
const [loding, setloding] = useState(false); //loding;
const [childData, setChildData]: any = useState(); //获取子组件的值
const childMethodRef:any = useRef();
const changeloding = () => {
setloding(true);
setTimeout(() => {
setloding(false);
}, 1000);
};
const handleChildFun = () => {
childMethodRef.current.fun2()
};
const getchildfn = useCallback((data: any) => {
setChildData(data);
}, []);
return (
这是一个小小的button
{这是子组件的值{childData}}
{
handleChildFun();
}}
>
我要
);
};
export default Home;
子组件
import{ useEffect, useState ,useImperativeHandle,forwardRef} from "react";
import Countdown from "react-countdown";
import dayjs from "dayjs";
interface sister {
sisters: string;
setsisters: any;
handleChildData:any;
cRef:any
}
let Changeyears = (props: sister):any => {
const { sisters, setsisters,handleChildData,cRef } = props;
const [Cdtime,setCdtime]=useState(dayjs(1649999957832).valueOf())
const [childtext , setchildtext ] = useState('')
useImperativeHandle(cRef, () => ({
childFun (info: any) {
console.log(info)
},
fun2(){
console.log('fun2')
}
}));
useEffect(()=>{
handleChildData(childtext)
},[childtext])
return (
<>
{
const {days,hours,minutes,seconds} = time.formatted
return (
还有{days}天{hours}时{minutes}分{seconds}秒
)
}}
/>
{
setchildtext('今天给爸爸洗脚')
}}>传给父组件值
{
setchildtext('今天不给爸爸洗脚')
}}> 第二次传给父组件的值
{sisters}
>
);
};
Changeyears = forwardRef(Changeyears);
export default Changeyears;
import React, { useRef, useImperativeHandle } from 'react';
import ReactDOM from 'react-dom';
const FancyInput = React.forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return
});
const App = props => {
const fancyInputRef = useRef();
return (
)
}
ReactDOM.render( , root);
import React,{Component,useState} from 'react'
function useCountFather(initValue){
var [count,setCount]=useState(initValue)
function increase(){
setCount(++count)
}
function decrease(){
setCount(--count)
}
return [count,{increase,decrease}]
}
function Count(){
var [count,countFatherApi]=useCountFather(0)
return(
{count}
)
}
function App(){
return(
)
}
export default App;
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState({ hits: [] });
useEffect(async () => {
const result = await axios(
'https://hn.algolia.com/api/v1/search?query=redux',
);
setData(result.data);
});
return (
{data.hits.map(item => (
-
{item.title}
))}
);
}
export default App;
手动触发
function App() {
const [data, setData] = useState({ hits: [] });
const [query, setQuery] = useState('redux');
const [search, setSearch] = useState('');
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`http://hn.algolia.com/api/v1/search?query=${query}`,
);
setData(result.data);
};
fetchData();
}, [query]);
return (
setQuery(event.target.value)}
/>
{data.hits.map(item => (
-
{item.title}
))}
);
}
参考