Пересматривается ли родительский компонент, когда дочерний компонент возвращается с чем-то новым? - PullRequest
4 голосов
/ 10 марта 2019

Насколько я знаю, дочерний компонент перерисовывается при изменении state или props родительского компонента.

Но я понятия не имею с делом наоборот.

Вот код.

usePromise.js (выполненные на заказ крючки)

import { useEffect, useReducer } from 'react';

const reducer = (state, action) => {
    switch (action.type) {
        case 'RESOLVED':
            return { ...state, resolved: action.diff };
        case 'LOADING':
            return { ...state, loading: action.diff };
        case 'ERROR':
            return { ...state, resolved: action.diff };
        default:
            return state;
    }
};

export default function usePromise(promiseCreator, deps = []) {
    const [state, dispatch] = useReducer(reducer, {
        resolved: null,
        loading: false,
        error: null
    });

    const process = async () => {
        dispatch({ type: 'LOADING', diff: true });
        try {
            const result = await promiseCreator();
            dispatch({ type: 'RESOLVED', diff: result });
        } catch (e) {
            dispatch({ type: 'ERROR', diff: e });
        }
        dispatch({ type: 'LOADING', diff: false });
    };

    useEffect(() => {
        process();
    }, deps);

    return state;
}

usePromiseSample.js

import React from 'react';
import usePromise from './usePromise';

const wait = () => {
    return new Promise(resolve =>
        setTimeout(() => resolve('Hello hooks!'), 3000)
    );
};

const UsePromiseSample = () => {
    const { resolved, loading, error } = usePromise(wait);

    console.log('test')

    if (loading) return <div>loading...</div>;
    if (error) return <div>error happened!</div>;
    if (!resolved) return null;

    return <div>{resolved}</div>;
};

export default UsePromiseSample;

Как видно из приведенного выше кода, состояние дочернего (usePromise.js) компонента изменяется четыре раза.

Но похоже, что parent (usePromiseSample.js) также переопределяется четыре раза, так как test записывается четыре раза.

Как я могу легко понять эту ситуацию?

1 Ответ

1 голос
/ 10 марта 2019

usePromise не дочерний компонент, а пользовательский хук.Хук сам по себе не перерисовывается, когда действие отправляется внутри usePromise, но компонент, который его использует, есть.

Если вы визуализируете UsePromiseSample внутри другого компонента, вы увидите, что родительне повторный рендеринг при UsePromiseSample.

const { useEffect, useReducer } = React;

const reducer = (state, action) => {
  switch (action.type) {
    case 'RESOLVED':
      return { ...state, resolved: action.diff, loading: false };
    case 'ERROR':
      return { ...state, resolved: action.diff, loading: false };
    default:
      return state;
  }
};

function usePromise(promiseCreator, deps = []) {
  const [state, dispatch] = useReducer(reducer, {
    resolved: null,
    loading: true,
    error: null
  });

  const process = () => {
     promiseCreator()
       .then(result => {
         dispatch({ type: 'RESOLVED', diff: result });
       })
       .catch(e => {
        dispatch({ type: 'ERROR', diff: e });
       });
  };

  useEffect(() => {
    process();
  }, deps);

  return state;
}

const wait = () => {
  return new Promise(resolve =>
    setTimeout(() => resolve('Hello hooks!'), 3000)
  );
};

const UsePromiseSample = () => {
  const { resolved, loading, error } = usePromise(wait);

  console.log('UsePromiseSample rendered')

  if (loading) return <div>loading...</div>;
  if (error) return <div>error happened!</div>;
  if (!resolved) return null;

  return <div>{resolved}</div>;
};

const App = () => {
  console.log('App rendered')

  return <UsePromiseSample />
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
...