У меня есть компонент контейнера с модальным в нем, который открывается и закрывается на основе свойства состояния.
Я хочу контролировать это через URL-адрес, то есть хочу
/projects - the modal is NOT open
/projects/add - the modal IS open
Я хочу, чтобы ссылка на него напрямую связывалась, я хочу, чтобы URL-адрес изменился, когда я нажимаю ссылки в основном контейнере, чтобы открыть модальный.
Может кто-нибудь объяснить, как я могу это сделать, или указать мне в правильном направлении хорошего учебника?
ПРИМЕЧАНИЕ. Этот способ не является совершенным. Более того, это скорее антипаттерн, чем шаблон. Причина, по которой я публикую его здесь, это хорошо работает для меня, и мне нравится, как я могу добавлять модалы (я могу добавить модальный на любую страницу, и в целом их компоненты никак не зависят от другого приложения. url вместо уродливого ?modal=login-form
). Но будьте готовы получить проблемы, прежде чем вы найдете все, что работает. Подумай дважды!
Предположим, вы хотите, чтобы следующие URL:
/users
чтобы показать компонент <Users/>
/users/login
чтобы показать компонент <Users/>
и <Login/>
modal over it
Вы хотите, чтобы Login
не зависел от Users
в любом случае, скажем, добавив модем регистрации на другие страницы без боли.
Пусть у вас есть свой корневой компонент, который стоит поверх других компонентов. Например Users
render
может выглядеть примерно так:
render() {
return (
<Layout>
<UsersList />
</Layout>
);
}
А Layout
render
может выглядеть примерно так:
render() {
return (
<div className="page-wrapper">
<Header />
<Content>
{this.props.children}
</Content>
<Footer />
</div>
);
}
Хитрость заключается в том, чтобы заставить модальную инъекцию <Layout/>
каждый раз, когда нам это нужно.
Самый простой подход - использовать для него поток. Я использую редукцию и редуктор ui
для такой метаинформации страницы, вы можете создать ui
store, если используете другую реализацию потока. Во всяком случае, конечной целью является рендеринг модальности, если состояние <Layout/>
(или даже лучший реквизит) содержит modal
равное некоторой строке, представляющей модальное имя. Что-то вроде:
render() {
return (
<div className="page-wrapper">
<Header />
<Content>
{this.props.children}
</Content>
{this.props.modal ?
<Modal key={this.props.modal} /> :
null
}
<Footer />
</div>
);
}
<Modal/>
возвращает модальный компонент, зависит от заданного ключа (в случае нашего ключа login-form
мы хотим получить компонент <Login/>
).
Хорошо, отпустите на маршрутизатор. Рассмотрим следующий фрагмент кода.
const modal = (key) => {
return class extends React.Component {
static displayName = "ModalWrapper";
componentWillMount() {
// this is redux code that adds modal to ui store. Replace it with your flux
store.dispatch(uiActions.setModal(key));
}
componentWillUnmount() {
store.dispatch(uiActions.unsetModal());
}
render() {
return (
<div className="Next">{this.props.children}</div>
);
}
}
};
...
<Route path="users" component={Next}>
<IndexRoute component={Users}>
<Route path="login" component={modal('login-form')}>
<IndexRoute component={Users} />
</Route>
</Route>
(Не заботьтесь о Next
- я добавляю его здесь для простоты. Представьте, что это просто делает this.props.children)
Функция modal()
возвращает компонент реакции, который вызывает изменение в магазине ui
. Таким образом, как только маршрутизатор получает /users/login
он добавляет login-form
в ui
store, <Layout/>
получает его как prop (или состояние) и отображает <Modal/>
который отображает соответствующий для данного ключа модальный.
Чтобы программно оценить новый URL-адрес, передайте маршрутизатор вашему компоненту и используйте push. push
например, будет вызвано вызовом обратного вызова действием пользователя.
При настройке маршрутизатора установите маршрут в /projects/:status
. то на вашем маршруте компонента вы можете прочитать значение status
используя this.props.param.status
. Например, прочитайте " whats-it-look-lik " от реактивного маршрутизатора.
params
иpathname
кthis.props.params
и, возможно, обратиться к нему напрямую, чтобы управлять модалами.