React Hooks - przy użyciu useState vs. tylko zmienne

12

Haczyki React dają nam opcję useState i zawsze widzę porównania Hooks vs Klasa-Stan. Ale co z hakami i niektórymi regularnymi zmiennymi?

Na przykład,

function Foo() {
    let a = 0;
    a = 1;
    return <div>{a}</div>;
}

Nie użyłem Haków, a to da mi takie same wyniki jak:

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

Czym więc jest różnica? Korzystanie z haków jeszcze bardziej skomplikowane w tym przypadku ... Więc po co z tego korzystać?

Mosze Nagar
źródło
Porównujesz jednak 2 różne rzeczy. Druga funkcja z haczykami ma możliwość aktualizacji danych. Ten pierwszy tak naprawdę nic nie robi. Mogłeś go właśnie zainicjować let a = 1; return <div>{a}</div>i uzyskasz ten sam wynik.
Yathi,

Odpowiedzi:

13

Powodem jest to, useStateże ponownie wyświetla widok. Zmienne same w sobie zmieniają tylko bity w pamięci, a stan Twojej aplikacji może zsynchronizować się z widokiem.

Porównaj te przykłady:

function Foo() {
    const [a, setA] = useState(0);
    return <div onClick={() => setA(a + 1)}>{a}</div>;
}

function Foo() {
    let a = 0;
    return <div onClick={() => a + 1}>{a}</div>;
}

W obu przypadkach azmienia się po kliknięciu, ale tylko przy useStateprawidłowym użyciu widoku pokazuje aaktualną wartość.

marzelin
źródło
Dzięki! Więc jeśli nie muszę renderować widoku - to tylko sposób na uporządkowanie moich danych (rekwizytów) w jakąś tablicę - mogę użyć „let”? To działa dla mnie, chcę tylko wiedzieć, że jest w porządku i do zaakceptowania.
Moshe Nagar
@MosheNagar, jeśli wyprowadzasz dane z rekwizytów, zaleca się stosowanie lokalnych zmiennych zamiast utrzymywania danych w stanie, ponieważ komponent zrezygnuje po zmianie rekwizytu, aby widok był zsynchronizowany z danymi. Wprowadzenie ich w stan spowodowałoby tylko niepotrzebne ponowne wysyłanie - najpierw przy zmianie prop, a potem przy zmianie stanu.
marzelin
Jeszcze jednym sposobem spojrzenia na tę odpowiedź jest myślenie, że w drugim przypadku zmienna abędzie śmieciami zbieranymi po zakończeniu wykonywania, podczas gdy w pierwszym przypadku, ponieważ wykorzystuje useStatewartość, zachowa wartośća
João Marcos Gris,
Nadal mógłby skorzystać, useRefgdyby nie chciał ponownie renderować widoku. Pozostaje pytanie, czy powinien on używać zmiennych lokalnych czy referencji React. Np. Jeśli masz limit czasu, który musisz wyczyścić, lub bieżące żądanie HTTP za pomocą axios, czy przechowujesz limit czasu lub źródło axios w zmiennej lub w React ref?
Tom
3
@ Tom Ogólna zasada mówi o używaniu lokalnych zmiennych dla stanu pochodnego. Do czegokolwiek innego użyj useRef(jeśli nie chcesz ponownie wysłać) lub useState(jeśli chcesz ponownie wysłać). W przypadku timerów, ponieważ są to działania niepożądane, należy je rozpocząć od useEffectrazu. Jeśli chcesz timerIdtylko do celów czyszczenia, możesz zachować go w zmiennej lokalnej programu obsługi . Jeśli chcesz mieć możliwość wyczyszczenia timera z innego miejsca w komponencie, powinieneś użyć useRef. Przechowywanie timerIdw lokalnej zmiennej komponentu byłoby błędem, ponieważ lokalne zmienne są „resetowane” na każdym renderowaniu.
marzelin
1

Aktualizacja stanu spowoduje ponowne renderowanie komponentu, ale nie są to wartości lokalne.

W twoim przypadku wyrenderowałeś tę wartość w swoim komponencie. Oznacza to, że po zmianie wartości komponent powinien zostać zrenderowany, aby pokazać zaktualizowaną wartość.

Dlatego lepiej będzie użyć useStateniż normalnej wartości lokalnej.

function Foo() {
    let a = 0;
    a = 1; // there will be no re-render.
    return <div>{a}</div>;
}

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // re-render required
    return <div>{a}</div>;
}
Diament
źródło
0

Twój pierwszy przykład działa tylko dlatego, że dane zasadniczo nigdy się nie zmieniają. Punktem wejścia użycia setStatejest ponowne przesłanie całego komponentu, gdy stan się zmieni. Jeśli więc twój przykład wymagał zmiany stanu lub zarządzania stanem, szybko zdasz sobie sprawę, że konieczne będą zmiany wartości i aby zaktualizować widok o wartość zmiennej, będziesz potrzebować stanu i ponownego wyrenderowania.

10100111001
źródło
0
function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

jest równa

class Foo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            a: 0
        };
    }
    // ...
}

Jakie useStatezwroty to dwie rzeczy:

  1. nowa zmienna stanu
  2. ustawiający dla tej zmiennej

jeśli zadzwonisz setA(1), zadzwonisz this.setState({ a: 1 })i uruchom ponownie renderowanie.

Schogges
źródło
0

Zmienne lokalne zostaną zresetowane przy każdym renderowaniu po mutacji, a stan zaktualizuje:

function App() {
  let a = 0; // reset to 0 on render/re-render
  const [b, setB] = useState(0);

  return (
    <div className="App">
      <div>
        {a}
        <button onClick={() => a++}>local variable a++</button>
      </div>
      <div>
        {b}
        <button onClick={() => setB(prevB => prevB + 1)}>
          state variable b++
        </button>
      </div>
    </div>
  );
}

Edytuj serene-galileo-ml3f0

Drew Reese
źródło