RichTalk 是我们团队每 2 周一次的技术分享活动,前 5 分钟分享最近 2 周社区动态,接着一场技术分享
苏格拉底: 每个人都想告诉你怎样做才是对你自己好,他们不想让你自己去寻找答案,而是要你去相信他们。 丹:让我猜猜,你是想要我相信你说的对吧? 苏格拉底:才不是,我是要你好好从内心思考,而不是参考別人所说的。 -《深夜加油站遇见苏格拉底》又名《和平战士》
头条
有了 useEvent,和 useEffect 说再见吧
github.com/reactjs/rfc… React 团队新发布了一个 RFC,拟提供一个新的原生Hook —— useEvent。之所以叫 useEvent,是因为 React 团队认为这个 Hook 的主要应用场景是:封装事件处理函数。
function Chat() {
const [text, setText] = useState('');
// 🟡 Always a different function
const onClick = () => {
sendMessage(text);
};
return <SendButton onClick={onClick} />;
}
function Chat() {
const [text, setText] = useState('');
// 🟡 A different function whenever `text` changes
const onClick = useCallback(() => {
sendMessage(text);
}, [text]);
return <SendButton onClick={onClick} />;
}
function Chat() {
const [text, setText] = useState('');
const onClick = useEvent(() => {
sendMessage(text);
});
return <SendButton onClick={onClick} />;
}
他用于定义一个函数,这个函数有2个特性:
- 在组件多次 render 时保持引用一致
- 函数内始终能获取到最新的 props 与 state
可以很好的解决 hooks 存在的闭包陷阱问题。同时也可以在某些场景下 替代 useEffect;useEffect 里的每个值都是依赖,依赖变了 useEffect 重新执行,但一些场景下从需求上来看并不需要重新执行(rfc中有示例)。
大致的实现方案
// (!) Approximate behavior
function useEvent(handler) {
const handlerRef = useRef(null);
// In a real implementation, this would run before layout effects
useLayoutEffect(() => {
handlerRef.current = handler;
});
return useCallback((...args) => {
// In a real implementation, this would throw if called during render
const fn = handlerRef.current;
return fn(...args);
}, []);
}
扩展阅读:
精选
Top 6 JavaScript ES12 Features You Should Use
www.syncfusion.com/blogs/post/…
自 2015 年发布 ES6 以来,ECMAScript 的发展及其版本如下:
ES12 已于 2021 年 6 月发布, 我们一起再来回顾下其中的特性。
Promise.any()Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。 如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise
const err = new Promise((resolve, reject) => {
reject(new Error('Error'));
});
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('First Promise');
}, 200);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Second Promise');
}, 500);
});
Promise.any(\\\[err, p1, p2\\\]).then((res) => {
console.log(res);
})
// output: First Promise
const e1 = new Promise((resolve, reject) => {
reject(new Error('Error 1'));
});
const e2 = new Promise((resolve, reject) => {
reject(new Error('Error 2'));
});
Promise.any(\\\[e1, e2\\\])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
// output: "AggregateError: All promises were rejected"
WeakRef对另一个对象的弱引用
const student = {
name: 'John Doe',
age: 20,
address: {
number: 365,
street: 'Flower street'
}
}
const ref = new WeakRef(student);
ref.deref().age;
//output: 20
Private class methods私有方法和属性
class Auth {
#getToken() {
return "12345678";
}
isAuth() {
return this.#getToken();
}
}
const auth = new Auth();
auth.getToken(); //output: auth.getToken is not a function
auth.isAuth(); //output: 12345678
-
Logical assignment operators三个逻辑赋值运算符: -
逻辑空赋值 (??=)
-
逻辑与赋值 (&&=)
-
逻辑或赋值 (||=)
const person = { name: 'John' };
person.name ??= 'User 1';
console.log(person.name);
// output: John
person.age ??= 18;
console.log(person.age);
// output: 18
const product = { stocks: 10 };
product.stocks &&= 20;
console.log(product.stocks);
// output: 20
product.exp &&= '12/31/2021';
console.log(product.exp);
// output: undefined
const product = {
stocks: 0,
exp: '12/31/2021'
};
product.stocks ||= 10;
console.log(product.stocks);
// output: 10
product.exp ||= '01/31/2022';
console.log(product.exp);
// output: 12/31/2021
String.replaceAll()替换字符串中的所有子字符串
let str = 'hotdog dog'.replace(new RegExp('dog','g'), 'cat');
console.log(str) //output: hotcat cat
let str = 'hotdog dog'.replaceAll('dog', 'cat');
console.log(str) //output: hotcat cat
Numeric separators数字增加分隔符,可以使用_帮助我们分隔大数
let billion = 1_000_000_000;
console.log(billion); //output: 1000000000