RichTalk 快报 第 2 期

avatar
花呗借呗前端团队 @蚂蚁集团

image.png

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个特性:

  1. 在组件多次 render 时保持引用一致
  2. 函数内始终能获取到最新的 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 的发展及其版本如下:

image.png ES12 已于 2021 年 6 月发布, 我们一起再来回顾下其中的特性。

  1. 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"
  1. WeakRef对另一个对象的弱引用
const student = {
    name: 'John Doe',
    age: 20,
    address: {
      number: 365,
      street: 'Flower street'
    }
  }
const ref = new WeakRef(student);
ref.deref().age;
//output: 20
  1. 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
  1. Logical assignment operators 三个逻辑赋值运算符:

  2. 逻辑空赋值 (??=)

  3. 逻辑与赋值 (&&=)

  4. 逻辑或赋值 (||=)

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
  1. 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
  1. Numeric separators 数字增加分隔符,可以使用_帮助我们分隔大数
let billion = 1_000_000_000;
console.log(billion); //output: 1000000000

动态