#javascript #reactjs #redux #react-redux
#javascript #reactjs #redux #react-redux
Вопрос:
Я знаю, что это, вероятно, очень простой вопрос, но это скорее вопрос типа «Я не понимаю документы, пожалуйста, помогите мне».
Я пытаюсь соединить два компонента с помощью React-Redux: первый — это боковая панель, а второй — модальный, который должен появляться при нажатии на кнопку на боковой панели. Компоненты не связаны ни в каком родительско-дочернем отношении (кроме root), поэтому я предполагаю, что redux — лучший вариант.
Я прочитал все документы redux (и react-redux), и я понимаю основные концепции redux, но мне трудно понять, как их реализовать в моих компонентах.
По сути, я хочу кнопку на боковой панели, которая переключает сохраненное состояние (достаточно true / false), и в соответствии с этим состоянием модальное будет появляться ( state==true => display:block
) и исчезать с помощью кнопки в modal ( state==false => display:none
) .
Я думаю, мне нужно действие для переключения состояния, например:
const modalsSlice = createSlice({
name: 'modals',
initalState,
reducers: {
toggleModal(state, action){
state = !state;
}
}
});
затем соединяем действие в обоих компонентах (я пишу компоненты в классах, а не как функции), используя:
const toggleModal = {type: 'modals/toggleModal', payload: ''};
const mapStateToProps = state => state.showHideModal;
export default connect(mapStateToProps, toggleModal)(Component);
Теперь, предполагая, что я пока прав, я не уверен, как продолжить. Т.е. Как я предполагаю получить и внести изменения в сами компоненты? Конечно, мне нужно поместить функцию в кнопку со onClick={foo}
слушателем, но как foo
предполагается получать и обрабатывать состояние? И я полагаю showHideModal
, что нужно где-то инициализировать состояние? В корневом компоненте? При настройке хранилища?
Любая помощь будет высоко оценена.
Ответ №1:
Инициализация состояния
Предполагается, что вы инициализируете состояние showHideModal
в самом фрагменте. Более того, он должен быть назван как или showModal
или hideModal
для лучшей интерпретации того, что делает это состояние.
const modalSlice = createSlice({
name: 'modal',
initialState: {
showModal: false,
},
reducers: {
toggleModal(state){
state.showModal = !state.showModal;
}
}
});
export const { toggleModal } = modalSlice.actions;
Компонент боковой панели
Обработчик onClick
события должен быть передан явно через mapDispatchToProps .
import { toggleModal } from './modalSlice';
class Sidebar extends Component {
handleClick = () => {
const { toggleModal } = this.props;
toggleModal();
}
render() {
return (
<div>
{/* rest of JSX */}
<button onClick={this.handleClick}>Toggle Modal</button>
{/* rest of JSX */}
</div>
);
}
}
const mapDispatchToProps = {
toggleModal,
};
export default connect({}, mapDispatchToProps)(Sidebar);
Модальный
Примечание: вы не можете получить доступ к свойству напрямую из состояния, как вы это делали state.showHideModal;
. Сначала вам нужно получить доступ к фрагменту, а затем к свойству, присутствующему в нем state.modal.showHideModal;
.
class Modal extends Component {
handleClick = () => {
const { toggleModal } = this.props;
toggleModal();
}
render() {
const { showModal } = this.props;
return (
<>
{showModal ? (
<div>
<button onClick={this.handleClick}>Close</button>
</div>
) : null}
</>
);
}
}
const mapDispatchToProps = {
toggleModal,
};
const mapStateToProps = state => ({
showModal: state.modal.showModal,
});
export default connect(mapStateToProps, mapDispatchToProps)(Modal);
Обновить
Переходя к причине, по которой Redux выдает следующее предупреждение:
В действии в пути было обнаружено несериализуемое значение:
payload
Это потому, что SyntheticEvent передается в качестве полезной нагрузки для действия. Чтобы исправить это, вам нужно переместить toggleModal
вызов из функции onClick prop
в отдельную функцию-обработчик. Для справки, проверьте handleClick
функцию в модальном и боковой панели.
Комментарии:
1. Во-первых, вам не нужно определять
{ type, payload }
объект, поскольку Redux Toolkit обрабатывает его внутренне сtoggleModal
помощью action, что ничемmapDispatchToProps
не отличается. Во-вторых, я обновил ответ с помощью Modal.js . В-третьих, теперь так работает назначение деструктурирования ES6, пожалуйста, ознакомьтесь с документацией .2. Абсолютно! Вам не нужно переходить
showModal
из приложения в модальное, поскольку оно обрабатывается Redux. Просто оберните приложение<Provider />
с помощью хранилища в качестве реквизита, и все готово. Да, порядок деструктурирования не имеет значения, либо вы пишетеconst { foo, bar } = this.props;
, либоconst { bar, foo } = this.props;
он остается неизменным 🙂3. Нет, все еще ничего.
4. Хорошо, поэтому я добавил оператор if с
alert
in в него в редукторе, чтобы увидеть, действительно ли изменяется состояние (вы можете видеть в изолированной среде) — состояние действительно меняется! Это означает, что редуктор работает, но что-то вModal.js
коде не работает.5. В настоящее время единственный способ, которым я смог заставить его работать, — добавить
<Modal>
функциюSidebar
рендеринга. Но похоже, что я неправильно использую Redux (или, по крайней мере, не использую его в полной мере), потому что, насколько я понимаю, если я вкладываю<Modal>
внутрьSidebar
, нет никакого реального преимущества в использованииstore
, я могу сделать это с помощью обычного React .