react纯函数组件应用

React

index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, inital-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
	<script src="/main.js"></script>
</head>
<body>
	<div id="app"></div>
</body>
</html>

index.js

import React from 'react'
import ReactDOM from 'react-dom'
//这两个导入的时候必须用这样的接收名称
const myElement = React.createElement('h1',{ id: 'myElement',title: 'this is a element'},'someone')
const myBigElement = React.createElement('div',{ id: 'myBigElement',title: 'this is a big element'},'somebigone', myElement)
ReactDOM.render(myBigElement,document.getElementById('app')) 

纯函数组件

无状态组件可以通过减少继承Component而来的生命周期函数而达到性能优化的效果。从本质上来说,无状态组件就是一个单纯的render函数,所以无状态组件的缺点也是显而易见的。因为它没有shouldComponentUpdate生命周期函数,所以每次state更新,它都会重新绘制render函数。所以进一步

这里是个计数器Counter:

import React,{useState} from 'react';
import ReactDOM from 'react-dom';

function Counter(){
	const[num , setNum] =  useState(0);
	const click () => setNum(num + 1);
	return (<button onClick={click}>{num}</button>);
}

Memo

上面已经说到纯函数的组件将导致组件的重复渲染行为,进而造成好不容易优化出的性能,又被一定程度上打了折扣,这个时候我们需要Memo,Memo用来优化函数组件的重复渲染行为,当传入属性值都不变的情况下不会触发组件的重新渲染,否则就会触发组件的重新渲染。

用法
import React from "react";
import ReactDOM from 'react-dom';

function Counter(){
	const[num , setNum] =  useState(0);
	const click () => setNum(num + 1);
	return (<button onClick={click}>{num}</button>);
}
export default React.memo(Counter,isEqual)//第二个参数是渲染对比的自定义参数,默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现

Hooks API(钩子函数)

在这里插入图片描述
Hook是React 16.8(包括react-dom 16.8)新增的特性,它可以让你在不编写class的情况下使用state及其它的React特性,Hook是一个特殊的函数。

useState

通过在函数组件里调用useState来给组件添加一下内部的state

const [data,修改data的函数]=useState(data初始化的值);
import React,{useState} from 'react';
import ReactDOM from 'react-dom';

function Counter(){
	const[num , setNum] =  useState(0);
	const click () => setNum(num + 1);
	return (<button onClick={click}>{num}</button>);
}
//如果要修改状态的函数类似class组件的this.setState
function Test(){
	const[person , setObj] = useState({name:'lqq' , age:18});
	const click = () => setObj({ ...obj , age: obj.age + 1});//一定要解构出来,不然改不了值
	return(
		<>
			<p>{obj.name}</p>
			<button onClick={click}>{obj.age}</button>
		</>
	);
}

原理

let memoizedState;	
function useState (initialState) {	
  memoizedState = memoizedState || initialState	
  function setState (newState) {	
    memoizedState = newState	
    render()	
  }	
  return [memoizedState, setState]	
}
useEffect

useEffect在函数组件中执行副作用(钩子函数)的操作。

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://localhost/api/v1/search?query=${query}`,
      );
 
      setData(result.data);
    };
 
    fetchData();
  }, [query]);
 
  return (
    <Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <button type="button" onClick={() => setSearch(query)}>
        Search
      </button>
 
      <ul>
        {data.hits.map(item => (
          <li key={item.objectID}>
            <a href={item.url}>{item.title}</a>
          </li>
        ))}
      </ul>
    </Fragment>
  );
}
什么是副作用?

除了修改外部的变量,一个函数在执行过程中还有很多方式产生外部可观察的变化,比如说调用 DOM API 修改页面,或者你发送了 Ajax 请求,还有调用 window.reload 刷新浏览器,甚至是 console.log 往控制台打印数据也是副作用。

function Counter(){
	const[num , setNum] = useState(0);
	const saveCurrent = useRef();
	const click = () => {
		setNum(num + 1);
		saveCurrent.current = num + 1;
	};
	const alertHandle = () =>{
		 // 3秒延迟以后打印最新的值
	    setTimeout(() => {
	      console.log(saveCurrent.current);
	    }, 3000);
	};
	 return (
	    <>
	      <p>{num}</p>
	      <button onClick={click}>click</button>
	      <button onClick={alertHandle}>alert</button>
	    </>
  );
}
useMemo

useMemo是针对一个函数,是否多次执行,避免无用方法的调用,以此来节省性能损耗,他会返回一个该函数的,也就是调用函数并返回其结果

function Button({ name, children }) {
  function changeName(name) {
    console.log('11')
    return name + '改变name的方法'
  }
 
const otherName =  useMemo(()=>changeName(name),[name])//这样子做就不会因为改变其他非name的变量而调用changeName()
  return (
      <>
        <div>{otherName}</div>
        <div>{children}</div>
      </>
 
  )
}
 
export default Button
useCallback

useCallback针对一个函数,并返回该回调函数,他将返回函数本身,只有依赖发生变化时,才会调用

//有一个父组件,其中包含子组件,子组件接收一个函数作为 props ;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助 useCallback 来返回函数,然后把这个函数作为 props 传递给子组件;这样,子组件就能避免不必要的更新。这个例子中count变动时会重新选仍然子组件,但val变动时不会

function Parent() {
    const [count, setCount] = useState(1);
    const [val, setValue] = useState('');
 
    const getNum = useCallback(() => {
        return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
    }, [count])
 
    return <div>
        <Child getNum={getNum} />
        <div>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <input value={val} onChange={event => setValue(event.target.value)}/>
        </div>
    </div>;
}
 
const Child = React.memo(function ({ getNum }: any) {
    return <h4>总和:{getNum()}</h4>
})
useContext

组件之间共享状态,可以使用useContext()。

1.首先要进行导入createContext,useContext
import React,{useState,createContext,useContext} from 'react'
function Child(){
//在子组件中使用useContext进行接收父组件传递的上下文,这样值就能传递过来了
    const count1=useContext(CountContext)
    return (
        <h1>{count1}</h1>
    )
}
const CountContext=createContext()//首先创建一个上下文全局变量
function Example3(){
    const [count,setCount]=useState(0)

    function handleClick(){
        setCount(count+1)
    }
   
    return (
        <div>
            点击{count}
            <button onClick={handleClick}>clickme</button>
            其次是作为父组件将值传递过去,Provider 相当于提供者,Child是子组件
            <CountContext.Provider value={count}>
                <Child></Child>
            </CountContext.Provider>
        </div>
    )
}
export default Example3

useRef

useRef返回的是一个可变的ref对象,它的属性current被初始化为传入的参数(initialValue),返回的ref对象在组件的整个生命周期内保持不变

function TextInputWithFocusButton() {
  const inputEl = useRef();
  const getValue = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    console.log(inputRef.current.value)
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={getValue}>获取input的值</button>
    </>
  );
}

useQuery
function List(){
	const { data, isLoading, isError } = useQuery("list", async () => {
		const { data } = await axios.get("/api/list");
		return data
	});
	return <div>...</div>
}
useMutation
import { useMutation } from "react-query";
function App(){
	const [mutate] = useMutation(fn);
	async function onSubmit(){
		await mutate(
		{},
		{
			onSuccess: () => {
				console.log("Good Job!");
			},
			onError: () => {
				console.log("Error!")
			}
		);
	}
	return <button onclick={onSubmit}>提交</button>
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值