在自定义 React Hook 中维护多个状态值

问题描述 投票:0回答:3

我正在寻找一种干净的方法来在自定义反应挂钩中存储几个简单的值。必须返回多个 setter 和 getter 感觉很不舒服。我可以为每个值传递一个值,即

const modalState = useState(false)
,然后引用 modalState[0] 和 [1],但这感觉很奇怪。 我不喜欢下面的函数的是它返回 10 个值。看起来好像很多。

function useNotesModal() {
  const [showModal, setShowModal] = useState(false);
  const [modalNoteId, setModalNoteId] = useState(0); // if 0, means create note in modal
  const [modalNoteTitle, setModalNoteTitle] = useState("");
  const [modalNoteDescription, setModalNoteDescription] = useState("");
  const [modalNoteTagIds, setModalNoteTagIds] = useState([]);

  return {
    showModal,
    setShowModal,
    modalNoteId,
    setModalNoteId,
    modalNoteTitle,
    setModalNoteTitle,
    modalNoteDescription,
    setModalNoteDescription,
    modalNoteTagIds,
    setModalNoteTagIds,
  };
}
export default useNotesModal;
reactjs react-hooks
3个回答
3
投票

您可以批量返回值,例如 - 作为值和操作:

function useNotesModal() {
  const [showModal, setShowModal] = useState(false);
  const [modalNoteId, setModalNoteId] = useState(0); // if 0, means create note in modal
  const [modalNoteTitle, setModalNoteTitle] = useState("");
  const [modalNoteDescription, setModalNoteDescription] = useState("");
  const [modalNoteTagIds, setModalNoteTagIds] = useState([]);

  return {
    values: {
      showModal,
      modalNoteId,
      modalNoteTitle,
      modalNoteDescription,
      modalNoteTagIds
    },
    actions: {
      setShowModal,
      setModalNoteId,
      setModalNoteTitle,
      setModalNoteDescription,
      setModalNoteTagIds,
    }
  };
}

另一种选择是通过

value
set
自动批处理:

const { useState, useEffect } = React;

function useNotesModal() { 
  const states = {
    showModal: useState(false),
    modalNoteId: useState(0),
    modalNoteTitle: useState(""),
    modalNoteDescription: useState(""),
    modalNoteTagIds: useState([])
  }
  
  return Object.fromEntries(
    Object.entries(states)
      .map(([k, [value, set]]) => [k, { value, set }])
  );
}

const Demo = () => {
  const notesState = useNotesModal();
  
  useEffect(() => {
    setTimeout(() => {
      notesState.modalNoteId.set(101);
    }, 2000);
  }, []);
  
  console.log(notesState);
  
  return <div>{notesState.modalNoteId.value}</div>;
}

ReactDOM.render(
  <Demo />,
  root
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

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


2
投票

一种可能的方法是仅使用单个对象来保存状态,并返回该对象的 setter。

类似:

function useNotesModal() {
  const [state, setState] = useState({
    showModal: false,
    modalNoteId: 0,
    modalNoteTitle: "",
    modalNoteDescription: "",
    modalNoteTagIds: [],
  });
  

  function setFieldState(fieldName, value){
    setState({...state, [fieldName]: value});
  }

  return [state, setFieldState];
}

// Then, to use:

const [modalState, setModalState] = useNotesModal();

const showModal = modalState['showModal'];

setModalState("showModal", true);

这种情况下的关键是确保每次更新内部状态时都返回一个新对象。


0
投票

另一种方法是:

function useNotesModal() {
    const [showModal, setShowModal] = useState(false)
    const [modalNoteId, setModalNoteId] = useState(0) // if 0, means create note in modal
    const [modalNoteTitle, setModalNoteTitle] = useState('')
    const [modalNoteDescription, setModalNoteDescription] = useState('')
    const [modalNoteTagIds, setModalNoteTagIds] = useState([])

    const notesModal = React.useRef()
    if (notesModal.current === undefined) {
        notesModal.current = {
            showModal,
            setShowModal,
            modalNoteId,
            setModalNoteId,
            modalNoteTitle,
            setModalNoteTitle,
            modalNoteDescription,
            setModalNoteDescription,
            modalNoteTagIds,
            setModalNoteTagIds
        }
    }

    notesModal.showModal = showModal
    notesModal.modalNoteId = modalNoteId
    notesModal.modalNoteTitle = modalNoteTitle
    notesModal.modalNoteDescription = modalNoteDescription
    notesModal.modalNoteTagIds = modalNoteTagIds

    return notesModal
}
© www.soinside.com 2019 - 2024. All rights reserved.