什么是函数式编程
- 如果给定相同的参数,则返回相同的结果(也称为确定性)。
- 它不会引起任何副作用
确定性
let PI = 3.14;
const calculateArea = (radius) => radius * radius * PI;
calculateArea(10); // returns 314.0
这是一个计算面积的函数,圆周率是我们熟知的3.14,但如果有一天数学家们发现圆周率不是3.14,而是4.14了,那程序的执行结果会变成这样
let PI = 3.14;
const calculateArea = (radius) => radius * radius * PI;
calculateArea(10); // returns 414.0
可以看到虽然每次都是同样的参数,但是并没有得到同样的输出,这显然不是一个纯函数,我们稍微改造一下
let PI = 3.14;
const calculateArea = (radius, PI) => radius * radius * PI;
这样子函数的输出就不会被外部的变量影响,这就是纯函数的确定性
不会有副作用
下面的函数在执行时会影响到外部变量,这种副作用可能会导致我们的程序出现意料之外的bug
const arr = [2, 4, 6];
function addElement(arr, ele) {
arr.push(ele);
}
addElement(arr, 8);
console.log("original data", arr); // [2, 4, 6, 8]
我们稍微改一下代码
const arr = [2, 4, 6];
function addElement(arr, ele) {
return [...arr, ele];
}
console.log("modified data", addElement(arr, 8)); // [2, 4, 6, 8]
console.log("original data", arr); // [2, 4, 6]
这样子就不会影响到外部的变量,这就是函数式编程的不会引起副作用
函数式编程在react中的体现
reducer
const initialState = {
data: [],
loading: true
};
const reducer = (state = initialState, action: any) => {
switch (action.type) {
case "search":
return {
...state,
data: action.payload,
loading: false
};
default:
return state;
}
};
函数组件
const Counter = ({ count }) => {
return <h3>{`Count: ${count}`}</h3>;
};
setState
import { useState } from "react";
const App = () => {
const [count, setCount] = useState(0);
const handleClick = () => setCount(count + 1);
return (
// ...
);
};
const Counter = ({ count }) => {
// ...
};
export default App;
在setCount中,我们用了一个count变量而不是通过一个参数传递进去,这就有悖于函数式编程的概念,我们可以改一下这行代码
const handleClick = () => setCount((prev) => prev + 1);
可以看到,count的值便取决于传入callback中的参数prev,类比classComponent中的setState
data immutable 数据不可变
import { useState } from "react";
const App = () => {
const [person, setPerson] = useState({
fName: "",
lName: ""
});
const handleChange = (e) => {
setPerson({
...person,
[e.target.name]: e.target.value
});
};
return (
// ...
);
};
export default App;
react中我们通过setState去改变状态触发re-render,但是我们要赋予setState的是一个全新的data,而不是去改变原来的data,保证数据不可变,也是遵循函数式编程
避免副作用 useEffect
const Counter = ({ count }) => {
document.title = `Number of click: ${count}`;
return <h3>{`Count: ${count}`}</h3>;
};
这个组件中,我们改变了不属于这个组件的dom元素,产生了副作用,让组件变得不够纯粹,我们试着把这段副作用代码放到useEffect中
const Counter = ({ count }) => {
useEffect(() => {
document.title = `Number of click: ${count}`;
}, [count]);
return <h3>{`Count: ${count}`}</h3>;
};
HOC && renderProps
HOC和renderProps中也体现了函数式编程的思想,想了解的可以👇
你还不懂的React高阶指引?