DUICUO

これはオープンソース プロジェクトへの私の最初の PR 送信の記録です。

注:このahooksのソースコード解析シリーズはv3.3.13に基づいています。ソースコードは私が独自にコピーし、主にソースコードに解釈を加えました。詳細は[1]をご覧ください。

この記事はシリーズのボーナス記事として、オープンソースプロジェクトへの初めてのPR提出について記録したものです(以前にもPRを提出したことがあったと思いますが、ごくわずかな変更を加えました)。この記事が、より多くの人々がオープンソースプロジェクトに参加する助けになれば幸いです。

原因

ahooks についての記事をいくつか書いた後、公式の同僚からプライベート メッセージを受け取りました。

私はこのことにとても嬉しく思いましたが、同時に少し興奮と不安も感じました。

オープンソースへの参加はかつては手の届かない夢のように思えましたが、今では実際に実現できそうな気がして、ワクワクしています。もちろん、個人的な動機もあります。オープンソースプロジェクトへの貢献経験があれば、履歴書に大きくプラスになると思いませんか?

私の不安は、これまでオープンソース プロジェクトに参加したことがなく、うまくできるかどうか不安だということです。

専門家のアドバイスに基づいて、私はいくつかの問題に対処すること、つまりいくつかの問題の解決を支援することから始めることにしました。

問題またはニーズを定義する

そこで、ふと思いついて公式の問題を見てみたら、この問題を見つけました。問題の詳細[2]

以前、useRequestのソースコードを分析し、プラグインメカニズム[3]を使ってリクエストをエレガントにカプセル化する方法を学んだばかりでした。そこで、この問題を修正することにしました。

この問題の要件はシンプルです。障害発生後のポーリング試行の最大回数をサポートする必要があります。障害回数がこの値を超えた場合、ポーリングは停止されます。

コーディング前の準備

まず、公式のahooks GitHubからコピーをフォークしました。これは以前にもやったことがあります。

2番目のステップは、マスターブランチをベースにした機能ブランチに切り替えることです。手順は以下のとおりです。

 git チェックアウト-b 修正/ pollingSupportRetryCount

最後に、リポジトリに応じて異なる環境初期化操作がいくつかあります。ahookは次のとおりです。

 実行の初期化
糸の始まり

機能性

useRequest を使ったポーリングの現在の実装を見てみましょう。その原理は主に、リクエストが終了したら(成功か失敗かに関係なく)再リクエストし、setTimeout を使ってポーリングの効果を実現するというものです。

 最後に: () => {
// 一部のコードは省略されています...
// setTimeoutを使用したポーリング
timerRef .current = setTimeout (() => {
fetchInstance.refresh ();
}, ポーリング間隔);
},

私のアイデアは、オプション パラメータ pollingErrorRetryCount を定義することです。これはデフォルトで -1 に設定され、制限がないことを意味します。

現在の再試行回数を記録する別の変数を定義します。

 const countRef = useRef < 数値>( 0 );

開発者が pollingErrorRetryCount を設定し、再試行回数がその値を超えると、ポーリング ロジックを実行せずに直接戻ります。

成功または失敗した場合、現在の再試行回数を更新します。

 エラー発生時: () => {
countRef.current + = 1 ;
},
成功時: () => {
countRef.current = 0 ;
},

リクエストが終了したら、再試行回数が開発者が設定した制限に達しているかどうかを確認します。達していない場合は再試行操作を実行します。達している場合は、再試行回数をリセットしてポーリングを停止します。

 最後に: () => {
もし
ポーリングエラー再試行回数=== -1 ||
// エラー発生した場合pollingErrorRetryCount 回の再試行後にリクエストは繰り返さませ
( ポーリングエラー再試行回数! == -1 && countRef .current <= ポーリングエラー再試行回数)
){
// 一部のコードを無視する
timerRef .current = setTimeout (() => {
fetchInstance.refresh ();
}, ポーリング間隔);
} それ以外{
countRef.current = 0 ;
}
},

テストケース

全体的な変革はそれほど難しくなかったのですが、テストケースを書く際に問題に直面するようになりました。これは、フロントエンドのテストケースをほとんど書かず、主にフックテストケースに重点を置いているためです。この部分に最も多くの時間を費やしました。

最終的な使用例は次のとおりです。

 // 一部のコードは省略されています...
// リクエストエラーの場合はpollingErrorRetryCount 設定します
// 連続した失敗回数pollingErrorRetryCount を超える ポーリングは停止します
フック2 をレットします;
errorCallback を実行します
行為(() => {
errorCallback = jest.fn ();
hook2 = setUp (() => request ( 0 ), {
ポーリングエラー再試行回数: 3
ポーリング間隔: 100
pollingWhenHidden : true
onError : errorCallback
});
});
expect ( hook2 .result .current .loading ) .toEqual ( true ) ;
errorCallback を期待します。toHaveBeenCalledTimes ( 0 );
行為(() => {
jest.runAllTimers ();
});
hook2.waitForNextUpdate () を待機します
expect ( hook2 .result .current .loading ) .toEqual ( false );
errorCallback .toHaveBeenCalledTimes ( 1 ) を期待します
行為(() => {
jest.runAllTimers ();
});
hook2.waitForNextUpdate () を待機します
errorCallback .toHaveBeenCalledTimes ( 2 ) を期待します
行為(() => {
jest.runAllTimers ();
});
hook2.waitForNextUpdate () を待機します
errorCallback .toHaveBeenCalledTimes ( 3 ) を期待します
行為(() => {
jest.runAllTimers ();
});
hook2.waitForNextUpdate () を待機します
errorCallback .toHaveBeenCalledTimes ( 4 ) を期待します
行為(() => {
jest.runAllTimers ();
});
errorCallback .toHaveBeenCalledTimes ( 4 ) を期待します
行為(() => {
hook2.result.current.run ();
});
行為(() => {
jest.runAllTimers ();
});
hook2.waitForNextUpdate () を待機します
errorCallback .toHaveBeenCalledTimes ( 5 ) を期待します
hook2.アンマウント();
// 一部のコードは省略されています...

このテストケースのロジックを簡単に説明すると、3回再トレースするように設定しました。エラー発生後、テストは3回実行されるため、`errorCallback` は4回呼び出されます(エラー発生時を含む)。5回目の実行では `errorCallback` は呼び出されないため、依然として4回呼び出されます。その後、`errorCallback` が5回実行されることを想定して、手動でリクエストを実行します。

ここで問題が発生しました。5番目のリクエストで、タイマーの実行を待つ関数を以前記述していたのですが、実際には実行されず、エラーが頻繁に発生していました。この問題の解決に長い時間がかかりました。以下のコードを削除したら、ようやく動作するようになりました。

 行為(() => {
jest.runAllTimers ();
});
- hook2.waitForNextUpdate () を待機します
errorCallback .toHaveBeenCalledTimes ( 4 ) を期待します

ドキュメントとデモの補足

結局のところ、新しい API パラメータが追加され、ドキュメントに記載する必要があり、中国語と英語の両方のドキュメントを補足する必要があり、さらにデモ例も追加されました。

広報

上記の手順を完了したら、コードを送信できます。送信すると、別の場所からコピーしたプロジェクトにコードが表示されます。

「比較とプルリクエスト」(画像で強調表示)をクリックすると、次の画像が表示されます。

ブランチはデフォルトで選択されています。そこに情報を入力するだけで、以前に送信したメッセージを変更することもできます。このコミットの内容を英語で説明するのが最適です。

最後に、「送信」をクリックすれば完了です。

以下に示すように、PR を送信するためのエントリ ポイントもあります。

最後に、公式の回答を待つだけです(上記の実装は回答後に一部修正されました)。PRはマスターにマージされました。

要約と考察

オープンソースプロジェクトにプルリクエスト(PR)を送信するのはそれほど複雑なプロセスではありません。重要なのは要件の変更です。多くの場合、複数のエッジケースを考慮する必要がありますが、そこでフロントエンドのユニットテストが役立ち、あらゆるシナリオに対応できるようになります。

さらに、オープンソース プロジェクトに参加した経験がない人にとっては、ahooks のようなライブラリが良い選択肢だと思います。

  • モジュール区分がより明確になり、モジュールの機能を変更した場合の影響をより正確に予測できるようになりました。初心者にとってより使いやすくなっています。
  • ロジックは比較的シンプルです。実際、多くのコードは既にビジネスプロジェクトの utils/hooks フォルダ内に存在するかもしれません。
  • コミュニティは非常に活発で、メンテナーは迅速に対応できます。

これが皆様のお役に立てれば幸いです。

参考文献

[1]詳細: https://github.com/GpingFeng/hooks.

[2]問題の詳細: https://github.com/alibaba/hooks/issues/1645.

[3]プラグインメカニズムを使用してリクエストをエレガントにカプセル化する方法: https://juejin.cn/post/7105733829972721677。