Я играю с Flux, и он отлично работает, но сейчас я пытаюсь использовать его таким образом, чтобы хранилище потоков определяло одну точку правды или состояния для всех дочерних компонентов.
IЯ в основном пытаюсь реализовать систему аутентификации, которая определяет состояние аутентификации текущего пользователя без необходимости обновлять состояние каждого компонента в отдельности (их много), выполнив что-то вроде этого:
state = {
authenticated: AuthStateStore.getState(),
uid: AuthStateStore.getUid(),
token: AuthStateStore.getToken(),
username: AuthStateStore.getUsername(),
avatar: AuthStateStore.getAvatar(),
errors: []
}
* 1005Я подумал, что мог бы установить состояние для основного родительского компонента
<App/>
(из которого все остальное отображается как дочерний элемент), а затем передать состояние в качестве подпорки всем дочерним элементам.Это действительно работает -
{this.props.state.authenticated}
покажет правильное состояние от
<App/>
в дочерних элементах - но реквизиты являются неизменными, что означает, что когда состояние
<App />
обновляется через хранилище потоков, ни один из реквизитов, отправляемых дочерним элементам, необновлены новыми значениями из
<App/>
.
Есть ли способ достичь того, что я пытаюсь сделать здесь, или мне нужно установить состояние из хранилища потоков в каждом компоненте, для которого требуется информация втаким образом?
РЕДАКТИРОВАТЬ: как я передаю состояние с <App/>
(я обрезал жир, чтобы они были более читабельными).
App (Основной родитель)
class App extends Component {
state = {
authenticated: AuthStateStore.getState(),
uid: AuthStateStore.getUid(),
token: AuthStateStore.getToken(),
username: AuthStateStore.getUsername(),
avatar: AuthStateStore.getAvatar()
}
render() {
return (
<BrowserRouter>
<div>
<Sidebar state={this.state}/>
<Switch>
<Route exact path="/" component={Home} state={this.state}/>
<Route exact path="/signup" component={Signup} state={this.state}/>
<Route path="/activate/([\da-f]+)" component={Activate}/>
.......
</Switch>
<Footer />
</div>
</BrowserRouter>
);
}
}
Боковая панель (первый ребенок)
class Sidebar extends Component {
render() {
return (
<div className="sidebar">
<Navigation state={this.props.state}/>
<Search/>
</div>
);
}
}
Навигация (Второй ребенок)
class Navigation extends Component {
render() {
if (this.props.state.authenticated === "true") {
return (
<div>
<p>Authenticated content here</p>
</div>
);
} else {
return (
<div>
<p>Non-authenticated content here</p>
</div>
);
}
}
}
Приведенный выше код работает при первой загрузке, но если состояние <App/>
изменяется через хранилище потоков, это не отражается на дочерних элементах, если вы не выполните полную перезагрузку страницы (что мы явно не хотим делать).
Дальнейшее редактирование ...
Просто чтобы быть кратким, прямо сейчас ячтобы все работало, выполняя следующие действия в каждом дочернем компоненте, для которого требуется информация о состоянии Auth (снова жирная обрезка для удобства чтения) ...
class Navigation extends Component {
state = {
authenticated: AuthStateStore.getState(),
uid: AuthStateStore.getUid(),
token: AuthStateStore.getToken(),
username: AuthStateStore.getUsername(),
avatar: AuthStateStore.getAvatar()
}
componentWillMount() {
AuthStateStore.on("change", () => {
this.setState({
authenticated: AuthStateStore.getState(),
uid: AuthStateStore.getUid(),
token: AuthStateStore.getToken(),
username: AuthStateStore.getUsername(),
avatar: AuthStateStore.getAvatar()
});
});
}
render() {
if (this.state.authenticated === "true") {
return (
<div>
<p>Authenticated content here</p>
</div>
);
} else {
return (
<div>
<p>Non-authenticated content here</p>
</div>
);
}
}
}
... но в духе DNRY и пытаясь избежать каких-либо потенциальных ловушек из-за забвения вызова или установки состояния в компоненте где-то, я ищу альтернативное решение «одного окна», которое, я надеялся, может обеспечить Flux.