Я новичок в React и Redux, и в настоящее время я работаю над проектом React и у меня есть несколько вопросов об интеграции Redux.
1. Состояние загрузки асинхронно
У меня есть index.js
файл, который является точкой входа в мой проект:
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router } from 'react-router-dom'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
ReactDOM.render(
<Provider store={store}>
<Router>
<App />
</Router>
</Provider>,
document.getElementById('root')
)
Здесь я импортирую store.js
:
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers'
const store = createStore(
rootReducer,
applyMiddleware(thunk)
)
export default store
И App.js
:
import React, { Component } from 'react'
import { Route } from 'react-router-dom'
import UserRoute from './components/UserRoute'
import GuestRoute from './components/GuestRoute'
import Menu from './components/Menu'
import LoginPage from './components/pages/LoginPage'
import SignupPage from './components/pages/SignupPage'
import HomePage from './components/pages/HomePage'
import ProfilePage from './components/pages/ProfilePage'
import GroupsPage from './components/pages/GroupsPage'
class App extends Component {
render() {
return (
<div>
<Menu />
<Route exact path="/" component={HomePage} />
<GuestRoute exact path="/login" component={LoginPage} />
<GuestRoute exact path="/signup" component={SignupPage} />
<UserRoute exact path="/profile" component={ProfilePage} />
<UserRoute exact path="/groups" component={GroupsPage} />
</div>
)
}
}
export default App
Я сократил код, чтобы сделать его более читабельным для вас. Обратите внимание на UserRoute
и GuestRoute
компоненты. UserRoute
позволяет только аутентифицированным пользователям переходить на страницу, а GuestRoute
делает наоборот. У меня есть токен пользователя, сохраненный в localStorage
, затем я использую его для получения пользовательских данных с сервера. Я хочу получить ответ перед рендерингом моего App
компонента. Если я не жду ответа и мое местоположение, например, /profile
, то UserRoute
перенаправит меня на главную страницу. Чтобы избежать перенаправления, я могу сделать это:
getState().then(() => {
ReactDOM.render(
<Provider store={store}>
<Router>
<App />
</Router>
</Provider>,
document.getElementById('root')
)
})
Но это хороший способ загрузить состояние перед рендерингом? Или есть другие "лучшие" способы сделать это?
2. Импорт магазина в другие файлы
Как узнать текущее состояние в запросе axios? Можно ли экспортировать магазин в store.js
, а затем импортировать его в api.js
файл:
import axios from 'axios'
import store from './store'
const client = axios.create({
baseURL: 'http://localhost:3001',
headers: { 'Content-type': 'application/json' }
})
// Used to set current JWT token(part of third question)
export function setAuthorizationHeader(token = '') {
if (token) {
client.defaults.headers.common['Authorization'] = `Bearer ${token}`
} else {
delete client.defaults.headers.common['Authorization']
}
}
export default {
user: {
fetch() {
return client.get('/user').then(res => res.data)
},
// other api calls which use current state of store
}
}
3. Не чистые создатели действий
Этот вопрос о создателях действий. У меня есть следующие создатели действий:
import api, { setAuthorizationHeader } from '../api'
export function setUser(user) {
return { type: 'SET_USER', user }
}
export function setUserToken(token) {
return { type: 'SET_USER_TOKEN', token }
}
export const login = credentials => async dispatch => {
const { user, token } = await api.user.login(credentials)
// TODO: refactor this
setAuthorizationHeader(token)
dispatch(setUserToken(token))
dispatch(setUser(user))
}
Когда я получаю ответ от сервера, я устанавливаю заголовок Authorization
для клиента axios. Это нормально, что они не являются чистыми функциями?
Также вы можете заглянуть в мой репозиторий , чтобы лучше понять, как работает код.