[Suggestion]: Make useEffectEvent be usable by default in the challenges or add a new note for useRef's alternative
还没有人认领这个 Issue。
- 主要语言
- JavaScript
- 星标
- 11.8k
- 派生
- 7.9k
- 平均合并
- 1 天 11 小时
- 30 天内合并 PR
- 11
描述
Summary
Make useEffectEvent be usable by default in Separating Events from Effects' challenges, or add a new note for useRef's alternative.
Page
https://react.dev/learn/separating-events-from-effects
Details
I attempted to solve the first challenge in Separating Events from Effects with useEffectEvent. First, following the previous example, I imported that function with this line:
import { experimental_useEffectEvent as useEffectEvent } from 'react';
Then, I used it with these lines:
const updateCount = useEffectEvent(() => {
setCount(c => c + increment);
});
However, this error was shown up:
Runtime Error
App.js: _react.experimental_useEffectEvent is not a function (8:37)
5 | const [count, setCount] = useState(0);
6 | const [increment, setIncrement] = useState(1);
7 |
> 8 | const updateCount = useEffectEvent(() => {
^
9 | setCount(c => c + increment);
10 | });
11 |
Therefore, by default, I can't use useEffectEvent for that exercise. I wrote "by default" because maybe it can be used by opening it in CodeSandbox. It looks like an extra effort for me, so I haven't tried it yet.
One of the solution I found for this challenge is using useRef. I think, the key for this challenge is how to avoid passing reactive elements to the Effect. Because useRef somehow can be treated as local variable which can be changed outside of render, and the interval itself is in-between render, I think it's safe to use. I need to make a Ref consistent with increment state. So, I modified each callback function of the increment buttons.
Here is my solution:
import { useState, useEffect, useRef } from 'react';
export default function Timer() {
const [count, setCount] = useState(0);
const [increment, setIncrement] = useState(1);
const incrementRef = useRef(1);
function decreaseIncrement() {
const prevIncrement = increment;
const newIncrement = prevIncrement - 1;
setIncrement(newIncrement);
incrementRef.current = newIncrement;
}
function increaseIncrement() {
const prevIncrement = increment;
const newIncrement = prevIncrement + 1;
setIncrement(newIncrement);
incrementRef.current = newIncrement;
}
useEffect(() => {
const id = setInterval(() => {
const localIncrement = incrementRef.current;
setCount(c => c + localIncrement);
}, 1000);
return () => {
clearInterval(id);
};
}, []);
return (
<>
<h1>
Counter: {count}
<button onClick={() => setCount(0)}>Reset</button>
</h1>
<hr />
<p>
Every second, increment by:
<button disabled={increment === 0} onClick={() => {
decreaseIncrement()
}}>–</button>
<b>{increment}</b>
<button onClick={() => {
increaseIncrement();
}}>+</button>
</p>
</>
);
}
It would be better if the useRef's alternative is included as a new note in Separating Events from Effects section.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 Separating Events from Effects 页面开始,使用文档中说明的 useEffectEvent import 重现第一个 challenge。确定 challenge 环境是否应支持该 API,或者页面是否应说明 useRef 替代方案;当所选方案已在 challenge 及其相关指导中可用或得到清晰说明时,即视为完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- javascript, react
- 领域
- documentation
- Issue 类型
- 文档
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 38/100