#reactjs #react-hooks
Вопрос:
Я ищу простой способ хранения нескольких простых значений в пользовательском крючке react. Неудобно, когда приходится возвращать множество сеттеров и геттеров. Я мог бы передать по одному значению для каждого, то есть 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;
Комментарии:
1. Я не уверен, что понимаю ваш вопрос. Вы имеете в виду, что хотите иметь, возможно, несколько независимых модалов, использующих хук для хранения их состояния, и состояние каждого модала может иметь несколько полей? Или просто вы не хотите возвращать несколько параметров и значений с крючка?
2. @MattMorgan, я ищу лучший шаблон для подражания, который не был бы безумно сложным с редукторами. Может быть, вычисляемые свойства интегрированы с оператором распространения? Просто кажется, что это плохо масштабируется.
3. Но контекст (что именно является целью) может быть действительно важным, чтобы предложить лучшую альтернативу. Скажем , для этой конкретной структуры я думаю, что передача
modalNoteId
и т.modalNodeTitle
Д. В качестве аргументов хука Может быть намного удобнее, чем возвращаемые сеттеры для каждого из них.4. @skyboyer, кажется неудобным затем использовать аргументы возврата, такие как: modelNoteId[1](101);
Ответ №1:
Вы можете паковать возвращаемые значения, например, в виде значений и действий:
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>
Комментарии:
1. чего бы хотел аналогичный сеттер
console.log(notesState);
?2. Я понимаю, что могу получить значение с помощью xxx.modalNoteId.value, но теперь следуйте инструкциям, как установить значение?
3. Запустите фрагмент и посмотрите на результаты (или в консоли браузера) —
notesState. modalNoteId.set
.4. Я попробовал xxx.modalNoteId.set(101) и получил ошибку отправки. Не могли бы вы обновить свой образец, пожалуйста? Это помогло бы.
5. Это работает. Обновил пример. Повторите пример еще раз.
Ответ №2:
Один из возможных подходов состоял бы в том, чтобы просто использовать один объект для сохранения состояния и возвращать задатчик для этого объекта.
Что-то вроде:
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);
Ключ в этом случае состоит в том, чтобы гарантировать, что вы возвращаете новый объект каждый раз, когда обновляется внутреннее состояние.