Jotai(완전 Redux는 아님) 개발 도구

최근에 우리는 조사Jotai를 시작했는데 이것은 Recoil 대체Poimandres의 상태 관리이다.이 밖에 우리는 기존의 반충격 응용 프로그램을 Jotai로 바꾸는 경형 조사도 기록했다.이 연습을 실행할 때, 그것은 우리로 하여금 어떤 디버깅 도구가 조태를 겨냥한 것일지 생각하게 했다.불행하게도 이 글을 쓸 때 사용할 수 있는 것은 갈고리 useDebugValue 뿐이다.
현재, 대다수 사람들과 마찬가지로, 우리는 기능이 강하고 통용되는 개발 도구, 예를 들면 React DevTools, React Query DevTools 등을 즐겨 사용한다. 비록 우리는 과거에 생산 능력에서 Redux 을 사용하지 않았지만, 우리는 시종 ReduxDevTools 디버깅 React 상태 관리 시스템을 더욱 즐겨 사용한다.사실상, 우리는 계약 업무에서 사용하는 모든 주 관리 시스템을 위해 사용자 정의 내부 플러그인을 만들었다.본문을 작성할 때 우리는 아직 조태 플러그인을 찾지 못했기 때문에 자연스레 조태 플러그인을 만드는 것이 서로 영향을 미칠 수 있다고 생각한다.

우선 Config, Message, ConnectionResult, Extension 등에 Redux DevTools에서 Redux DevTools로 전송되는 유효 부하와 일치하는 인터페이스/유형을 설정했습니다.이 인터페이스들은 Browser Extension 본체와 통신하는 강한 유형의 맵을 지원한다.
interface Config {
    instanceID?: number,
    name?: string,
    serialize?: boolean,
    actionCreators?: any,
    latency?: number,
    predicate?: any,
    autoPause?: boolean
}

interface Message {
    type: string,
    payload?: any,
    state?: any
}

interface IConnectionResult {
    subscribe: (dispatch: any) => {};
    unsubscribe: () => {};
    send: (action: string, state: any) => {};
    error: (payload: any) => {};
}

type ConnectionResult = IConnectionResult & Observable<Message>

interface Extension {
    connect: (options?: Config) => ConnectionResult;
}
불행하게도 브라우저 확장 전단에 사용되는 Redux DevTools connect 함수는 표준 RxJS 관찰 가능한 값을 되돌려 주지 않았습니다.따라서 RxJS가 호환되는 관찰 가능한 대상이 Redux DevTools 이벤트를 수신할 수 있도록 wrapConnectionResult 함수가 필요합니다.
const wrapConnectionResult = (result: ConnectionResult) => {
    const subject = new Subject<Message>()

    result.subscribe(
        (x: any) => subject.next(x),
        (x: any) => subject.error(x),
        () => {subject.complete()}
    );

    return subject;
}
이제 사용자는 DevTools 인스턴스를 명명하고 구성할 수 있도록 JotaiDevtoolsProps 인터페이스를 구현할 것입니다.
interface JotaiDevtoolsProps {
    atom: WritableAtom<any, any>,
    name?: string,
    config?: Config
}
React 기능 구성 요소와 틈새 없는 통합을 실현하기 위해 갈고리를 만들었습니다. 이 갈고리는 우리의 Jotai Devtools Props를 가져와 특정한 Jotai atom의 실례를 실례화합니다.
...
export const useJotaiDevtools = ({ atom, name, config, ...props }: JotaiDevtoolsProps) => {
...
다음은 observable-hooks 라이브러리의 useObservable hook 를 사용하여 RxJS의 관찰 가능한 값으로 전송된 원자의 값을 제공할 것입니다.
    const atom$ = useObservable((input$) => input$.pipe(
        map(([x]) => x)
    ), [atomCurrentValue]);
원자 업데이트 시 충돌 상황을 방지하기 위해 마지막 상태 업데이트가 Redux DevTools 시간 여행 이벤트인지 확인하기 위해 로고를 추가합니다.
    const [wasTriggeredByDevtools, setWasTriggeredByDevtools] = useState(() => false);

또한 초기 상태가 DevTools 확장으로 전송되었는지 확인하는 플래그가 필요합니다.
    const [sentInitialState, setSentInitialState] = useState(() => false);

    const [devTools, setDevTools] = useState<ConnectionResult>();
DevTools 연결은 갈고리를 초기화할 때 사용할 수 없기 때문에 연결이 완료될 때 정리된 이벤트 흐름을 제공하기 위해 다른 useObservable 를 추가합니다.
    const devTools$ = useObservable((input$) => input$.pipe(
        filter(([x]) => !!x),
        switchMap(([x]) => wrapConnectionResult(x as ConnectionResult)),
        catchError((error, observable) => {
            console.error(error);
            return observable;
        })
    ), [devTools]); 
이 함수는 상태 점프와 시간 여행 이벤트를 처리하는 데 사용됩니다.
    const jumpToState = (newState: any) => {
        setWasTriggeredByDevtools(true)
        // var oldState = atomCurrentValue();
        setAtom(newState);
        // setWasTriggeredByDevtools(false);
    };
이전 모드를 계속하면 observable-hookuseSubscription 갈고리를 사용하여 DevTools 확장 이벤트를 구독하고 현지 응답 시작이나 스케줄링 작업에 적합합니다.
    useSubscription(devTools$, (message) => {
        switch (message.type) {
            case 'START':
                console.log("Atom Devtools Start", options.name, atomCurrentValue)
                if(!sentInitialState) {
                    // devTools.send("\"" + options.name + "\" - Initial State", atom.getState());
                    devTools?.send(name + " - Initial State", atomCurrentValue);
                    setSentInitialState(true);
                }
                return;
            case 'DISPATCH':
                if (!message.state) {
                    return;
                }
                switch (message.payload.type) {
                    case 'JUMP_TO_ACTION':
                    case 'JUMP_TO_STATE':
                        jumpToState(JSON.parse(message.state));
                        return;
                }
                return;
        }
    });
다음은 현재 Jotai atom의 응용 프로그램 상태 변경에 대한 업데이트를 구독하기 위한 또 다른 useSubscribe 갈고리가 필요합니다.
    useSubscription(atom$, (state) => {
        if (wasTriggeredByDevtools) {
            setWasTriggeredByDevtools(false);
            return;
        }
        devTools?.send(name + " - " + moment().toISOString(), state);
    })
구성 요소를 초기화할 때, DevTools Extension 에 대한 인용을 얻기 위해 함수가 필요합니다.확장자가 설치되어 있지 않으면 콘솔에 오류가 기록됩니다.
    const initDevtools = () => {
        const devtools = (window as any).__REDUX_DEVTOOLS_EXTENSION__ as Extension;
        // const options = config;
        const name = options.name || window.document.title;

        if (!devtools) {
            console.error('Jotai Devtools plugin: Cannot find Redux Devtools browser extension. Is it installed?');
            return atom;
        }

        const devTools = devtools.connect(options);

        console.log("Get Dev Tools", devTools, of(devTools));

        setDevTools(devTools);

        // setTimeout(() => devTools.send(name + " - Initial State", atomCurrentValue), 50)

        return atom;
    }
우리의 초기화 함수를 활성화하기 위해서, 우리는 useLifeCycles 갈고리 (우수한 react-use 라이브러리) 를 이용하여 구성 요소가 불러오는 생명주기 이벤트를 처리할 것이다.
    useLifecycles(() => {
        initDevtools();
    });
그렇습니다.현재 사용Jotai Devtools plugin 항목에 새 Jotai atoms 만 설치하면 됩니다.
구체적으로 말하자면, 우리는 당신이 Devtool Browser Extension에서 보고 싶은 모든 원자 호출 useJotaiDevtools 갈고리를 제공할 수 있습니다
...
    useJotaiDevtools({
        name: "Dark Mode",
        atom: darkModeState
    });
...

    useJotaiDevtools({
        name: "Tasks",
        atom: tasksAtom
    });

...

설명을 위해 에서 Recoil 로 변환된 Jotai 예시를 반복해서 사용할 수 있습니다.프로그램이 시작되면 Redux DevTools Browser Extension 을 열 수 있습니다. 상태 변화, 시간 여행 디버깅 등을 볼 수 있습니다.

마지막 생각:

  • Redux DevTools에서 완성된 기존 작업을 이용하여 우리는 바퀴를 재발명하지 않고 유용한 디버깅 도움을 얻을 수 있다.
  • observable-hooks 라이브러리를 이용하여 깨끗하고 효율적인 Redux DevTools 통합을 실현하였다.
  • Redux DevTools의 시간 여행 기능을 조정하면 조태 상태 체인의 완전한 재생을 실현할 수 있다.
  • 그 결과 조태원자의 생명주기에 대해 눈길을 끄는 견해가 나왔다.
  • 보기Jotai Devtools Repo on Github!
  • 다음은 기능 예시입니다.설치되지 않은 경우 상태 업데이트를 보려면 설치Redux DevTools extension를 확인하십시오.

    좋은 웹페이지 즐겨찾기