Попытка достичь этой функциональности с помощью ловушек useEffect - PullRequest
0 голосов
/ 18 января 2020

Я просто поэкспериментировал с хуками React, чтобы лучше понять его, и подошел к этому варианту использования, указанному ниже.

Итак, я хочу, чтобы Sample Component показывал значение в верхнем регистре text на первом рендере, иначе точное значение текста, полученное им

Теперь, чтобы достичь этого, я должен использовать два useEffect

  1. Чтобы сделать текст значение в верхнем регистре для первого рендера
  2. Для обновления значения text при изменении / обновлении реквизита

Что я понял, используя этот подход, мое состояние ( Я думаю ) будет обновляться дважды, то есть с помощью хуков useEffect. Кроме того, мне придется сохранить ту же последовательность эффектов-ловушек, так как они выполняются в последовательности, и изменение последовательности приведет к тому, что первый рендер будет выплевывать обычный корпус значения text

Что может быть другой (лучший) способ добиться этого?

const { useState, useEffect } = React;
const { render } = ReactDOM;

const upperCase = str => str.toUpperCase();

const Sample = ({ text }) => {
  const [state, setState] = useState(upperCase(text));
  
  useEffect(() => {
    setState("text");
  }, [text]);
  
  useEffect(() => {
    setState(upperCase(text));
  }, []);

  return (
    <div>
      <p>{state}</p>
    </div>
  );
};

const App = () => {
  const [state, setState] = useState("Sample");
  return (
    <div>
      <Sample text={state} />
      {state}
      <input value={state} onChange={e => setState(e.target.value)} />
      <h3>App Component</h3>
    </div>
  );
};

render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>

Ответы [ 2 ]

3 голосов
/ 18 января 2020

Я считаю, что лучшим вариантом будет сделать это:

const Sample = ({ text }) => {
  const ref = useRef(false);

  useEffect(() => {
    ref.current = true;
  }, [text]);

  return (
    <div>
      <p>{ref.current ? text : text.toUpperCase()}</p>
    </div>
  );
};

Вы узнаете, является ли это первым рендером или нет, проверив значение ref.current.

0 голосов
/ 18 января 2020

просто используйте 1 useEffect в зависимости от изменения текста следующим образом:

const Sample = ({ text }) => {
  const [state, setState] = useState(upperCase(text));

  useEffect(() => {
    if (text !== state) setState(upperCase(text));
  }, [text]);

  return (
    <div>
      {console.log(state)}
      <p>{state}</p>
    </div>
  );
};
...