from 非同期なReactの状態更新をテストする resolveをawaitしたらたまたま動いたけど不適切 resolveの前にawaitをつけたらテストがたまたま通ったが、よく考えるとresolveはPromiseを返さないのでこれをawaitするのは筋が通らない TypeScriptも警告する: 'await' has no effect on the type of this expression. ts(80007) なぜこの書き方で動いたのかはまだよくわかってないが、少なくともこの書き方は正しい書き方ではないので、本題のストーリーに混ぜると混乱するから切り出しておくことにした。


下記のように書き換えると1,2,3,4,5,6,1,2,7の順で実行されるようになる。

ts

export const MyAsyncComponent = () => {
  const [value, setValue] = useState(0);
  console.log(1);
  userTrigger = () => {
    console.log(4);
    return new Promise<number>((res) => {
      resolve = res;
    }).then((x) => {
      console.log(6);
      setValue(x);
    });
  };
  console.log(2);
  return <span>{value}</span>;
};

ts

  render(<MyAsyncComponent />);
  expect(screen.getByText("0")).toBeTruthy(); 
  console.log(3);
  
  userTrigger();
  console.log(5);
  expect(screen.getByText("0")).toBeTruthy();
  
  await resolve(1);
  console.log(7);
 
  expect(screen.queryByText("0")).toBeNull();
  expect(screen.getByText("1")).toBeTruthy();

(追記: await resolve(1);はおかしい)

setValueでの更新をactで包むためにuseStateを差し替える

警告も消えてテストが通るようになった。めでたしめでたし。 full source code: https://gist.github.com/nishio/06249db25dafef81646d961ec9c0c70e