возможно ли React.useState (() = ›{}) в React?

можно ли использовать function в качестве состояния моего компонента React?

пример кода здесь:

// typescript 
type OoopsFunction = () => void;

export function App() {
    const [ooops, setOoops] = React.useState<OoopsFunction>(
        () => console.log('default ooops')
    );

    return (
        <div>
            <div onClick={ ooops }>
                Show Ooops
            </div>

            <div onClick={() => {
                setOoops(() => console.log('other ooops'))
            }}>
                change oops
            </div>
        </div>
    )
}

но это не работает ... defaultOoops будет вызываться в самом начале, и при нажатии change oops otrher ooops сразу же будет записан на консоль, не войдя в журнал после повторного нажатия Show Ooops.

Почему ?

Могу ли я использовать функцию в качестве состояния моего компонента?

или у React есть особые способы обработки таких the function state?


person eczn    schedule 10.04.2019    source источник


Ответы (3)


Можно установить функцию в состоянии с помощью хуков, но поскольку состояние может быть инициализировано и обновлено с помощью функции, которая возвращает начальное состояние или обновленное состояние, вам необходимо предоставить функцию, которая, в свою очередь, возвращает функцию, которую вы хотите вставить. штат.

const { useState } = React;

function App() {
  const [ooops, setOoops] = useState(() => () => console.log("default ooops"));

  return (
    <div>
      <button onClick={ooops}>Show Ooops</button>

      <button
        onClick={() => {
          setOoops(() => () => console.log("other ooops"));
        }}
      >
        change oops
      </button>
    </div>
  );
}

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>

person Tholle    schedule 10.04.2019
comment
Это было абсолютным спасателем! И, насколько я могу судить, без документов. Не могу понять, почему мои сохраненные функции не выполняются. Мне нравится, что setState принимает функцию при настройке, но мне нужно знать, как обернуть функцию в функцию, чтобы сохранить ее как состояние в лучшем случае неинтуитивно. Спасибо Спасибо спасибо! Никогда бы не догадался об этом ... - person sambecker; 27.12.2019
comment
Это тоже спасло мне жизнь. Моя проблема заключалась в том, что функция, которую я устанавливал в качестве переменной состояния, срабатывала без вызова. Сохранение его как функции, которая возвращает эту функцию, работает как шарм. Я согласен, что это нигде не задокументировано в документации по реакции. Спасибо! - person Seth Lutske; 01.10.2020
comment
Возможно, это не было задокументировано в прошлом, но теперь они есть. См. Раздел Ленивое начальное состояние, а также желтый поле выше, касающееся слияния обновлений, иначе говоря, с использованием prevState. Я также нашел эту статью полезной: medium.com/swlh/ - person Tyler Collier; 25.04.2021

TL;DR

Да, можно использовать функцию в качестве состояния компонента React. Для этого вы должны использовать функцию, возвращающую вашу функцию в React.useState:

const [ooops, setOoops] = React.useState<OoopsFunction>(
    () => () => console.log('default ooops')
);

// or

const yourFunction = () => console.log('default ooops');
const [ooops, setOoops] = React.useState<OoopsFunction>(
    () => yourFunction
);

Чтобы обновить функцию, вы также должны использовать функцию, возвращающую вашу функцию:

setOoops(() => () => console.log("other ooops"));

// or

const otherFunction = () => console.log("other ooops");
setOoops(() => otherFunction);

Подробный ответ

Примечания о React.useState

Подпись useState в React с типами:

function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];

Он показывает, что есть два способа установить начальное значение в вашем состоянии:

  1. Укажите начальное значение как есть (React.useState(0) - начальное значение 0),
  2. Предоставьте функцию, которая возвращает начальное значение, которое нужно установить (React.useState(() => 0) - начальное значение также 0).

Важное примечание: если вы предоставляете функцию в React.useState, то эта функция выполняется, когда выполняется React.useState, а возвращаемое значение сохраняется как начальное состояние.

Как на самом деле хранить функции

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

const [ooops, setOoops] = React.useState<OoopsFunction>(
    () => console.log('default ooops')
);

'default ooops' регистрируется немедленно, когда вызывается React.useState, и сохраняется возвращаемое значение (в данном случае undefined).

Этого можно избежать, предоставив функцию более высокого порядка, возвращающую вашу функцию, которую вы хотите сохранить:

const [ooops, setOoops] = React.useState<OoopsFunction>(
    () => () => console.log('default ooops')
);

Таким образом, внешняя функция будет определенно выполняться при первом запуске React.useState и ее возвращаемое значение будет сохранено. Поскольку это возвращаемое значение теперь является вашей обязательной функцией, эта функция будет сохранена.

Примечания о функции установки состояния

Сигнатура функции установки состояния (здесь setOoops) задается как

Dispatch<SetStateAction<S>>

с участием

type Dispatch<A> = (value: A) => void;
type SetStateAction<S> = S | ((prevState: S) => S);

Как и в React.useState, есть также возможность обновить состояние с помощью значения или функции, возвращающей значение. Таким образом, для обновления состояния также должна использоваться функция более высокого порядка, указанная выше.

person Peter Lehnhardt    schedule 10.04.2019

Предыдущие ответы установили меня на правильном пути, но мне нужно было немного настроить параметры setState, поскольку я хотел выполнить функцию с параметрами. Следующее сработало для меня!

const [handler, setHandler] = useState(() => {});

setHandler(() => () => enableScheduleById(scheduleId));
person CodeThief    schedule 30.04.2021