LoginSignup
2
0

More than 1 year has passed since last update.

npmパッケージのコードリーディングを100倍しやすくする方法

Last updated at Posted at 2022-04-19

100倍という表現はだいぶ大げさだと思うのですが、自分はこの方法を使ってからそれくらいnpmパッケージのコードリーディングがかなりしやすくなったので自分がこの方法を知った時の感覚をタイトルに反映させてみました!
方法というのはシンプルでnpmパッケージの気になる箇所にconsole.logを仕込んでデバックをするだけです!

今回はその「npmパッケージの気になる箇所にconsole.logを仕込んでデバックをする方法」について解説をします
デバックするライブラリはreact-hook-formにしました!

npmパッケージの気になる箇所にconsole.logを仕込んでデバックをする方法

少し手順が多いのですが、なるべくコピペするだけで良いようにしました!
また、一度この手順を踏めば次からのデバックはかなり楽になるはずです

1 適当なディレクトリを作り、そこにreact-hook-formをクローンする

mkdir react-hook-form_debug
cd react-hook-form_debug
git clone https://github.com/react-hook-form/react-hook-form.git

2 debug用のreactプロジェクトを作成し、react-hook-formをinstallする

yarn create react-app react-hook-form_code-reading --template typescript
cd react-hook-form_code-reading
yarn add react-hook-form
cd ..

3 react-hook-formをビルドする

cd react-hook-form
yarn
yarn build
cd ..

4 react-hook-formのパッケージと先程作成したreactプロジェクトをリンクさせる

cd react-hook-form_code-reading/node_modules/react-hook-form
rm -rf dist
ln -s ../../../react-hook-form/dist
cd ../..

lnコマンドはファイルやディレクトリのリンクを作るときに使うコマンド

5 reactプロジェクトでreact-hook-formを使用する

https://react-hook-form.com/get-started のコードをコピペしましょう

App.tsx
import React from "react";
import { useForm, SubmitHandler } from "react-hook-form";

type Inputs = {
  example: string,
  exampleRequired: string,
};

export default function App() {
  const { register, handleSubmit, watch, formState: { errors } } = useForm<Inputs>();
  const onSubmit: SubmitHandler<Inputs> = data => console.log(data);

  console.log(watch("example")) // watch input value by passing the name of it

  return (
    /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register("example")} />
      
      {/* include validation with required or other standard HTML validation rules */}
      <input {...register("exampleRequired", { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}
      
      <input type="submit" />
    </form>
  );
}

6 reactプロジェクトをスタートさせる

yarn start

もし以下のようなReactの重複参照エラーが発生した場合はreact-hook-formのReactのバージョンを利用する

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
cd node_modules
rm -Rf ./react ./react-dom
ln -s ../../react-hook-form/node_modules/react
ln -s ../../react-hook-form/node_modules/react-dom

※React18を利用する場合はindex.tsxファイルも修正する必要が有ります

index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(<App />, document.getElementById("root"));

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

7 react-hook-formのhandleSubmit関数にconsole.logを仕込む

createFormControl.ts
  const handleSubmit: UseFormHandleSubmit<TFieldValues> =
    (onValid, onInvalid) => async (e) => {
      console.log("submit!!") // console.logを追加
      if (e) {
        e.preventDefault && e.preventDefault();
        e.persist && e.persist();
      }
      let hasNoPromiseError = true;
      let fieldValues: any = cloneObject(_formValues);

      _subjects.state.next({
        isSubmitting: true,
      });

      try {
        if (_options.resolver) {
          const { errors, values } = await _executeSchema();
          _formState.errors = errors as FieldErrors<TFieldValues>;
          fieldValues = values;
        } else {
          await executeBuildInValidation(_fields);
        }

        if (
          isEmptyObject(_formState.errors) &&
          Object.keys(_formState.errors).every((name) => get(fieldValues, name))
        ) {
          _subjects.state.next({
            errors: {} as FieldErrors<TFieldValues>,
            isSubmitting: true,
          });
          await onValid(fieldValues, e);
        } else {
          if (onInvalid) {
            await onInvalid({ ..._formState.errors }, e);
          }

          _options.shouldFocusError &&
            focusFieldBy(
              _fields,
              (key) => get(_formState.errors, key),
              _names.mount,
            );
        }
      } catch (err) {
        hasNoPromiseError = false;
        throw err;
      } finally {
        _formState.isSubmitted = true;
        _subjects.state.next({
          isSubmitted: true,
          isSubmitting: false,
          isSubmitSuccessful:
            isEmptyObject(_formState.errors) && hasNoPromiseError,
          submitCount: _formState.submitCount + 1,
          errors: _formState.errors,
        });
      }
    };

8 react-hook-formをビルドする

別のターミナルを起動して

cd react-hook-form
yarn build

buildのwatchモードを使いたかったのですが、うまく動かなかったので断念

9 ブラウザで確認する

Screenshot from 2022-04-20 00-24-18.png
submit!!というのがlogで出力されているのを確認することが出来ると思います!
もし反映されていなかったらリロードしてみてください

いかがだったでしょうか?
この方法は他のパッケージのコードリーディングをするときもかなり使えると思うので、是非ためしてみてください!

参考資料
https://github.com/apollographql/apollo-client/blob/main/CONTRIBUTING.md

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0