我是一个反应新手,我从一开始就尝试使用react-redux风格。下面是我为一个简单的产品列表页面所做的尝试。
在我的App.js中检查用户是否仍在登录。
class App extends Component {
constructor(props) {
super(props);
this.state = {}
}
componentDidMount() {
if (isUserAuthenticated() === true) {
const token = window.localStorage.getItem('jwt');
if (token) {
agent.setToken(token);
}
this.props.appLoad(token ? token : null, this.props.history);
}
}
render() {
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => (
isUserAuthenticated() === true
? <Component {...props} />
: <Redirect to='/logout' />
)} />
)
return (
<React.Fragment>
<Router>
<Switch>
{routes.map((route, idx) =>
route.ispublic ?
<Route path={route.path} component={withLayout(route.component)} key={idx} />
:
<PrivateRoute path={route.path} component={withLayout(route.component)} key={idx} />
)}
</Switch>
</Router>
</React.Fragment>
);
}
}
export default withRouter(connect(mapStatetoProps, { appLoad })(App));
在my action.js appLoaded中,操作如下所示
export const appLoad = (token, history) => {
return {
type: APP_LOAD,
payload: { token, history }
}
}
用于它的reducer.js
import { APP_LOAD, APP_LOADED, APP_UNLOADED, VARIFICATION_FAILED } from './actionTypes';
const initialState = {
appName: 'Etsync',
token: null,
user: null,
is_logged_in: false
}
const checkLogin = (state = initialState, action) => {
switch (action.type) {
case APP_LOAD:
state = {
...state,
user: action.payload,
is_logged_in: false
}
break;
case APP_LOADED:
state = {
...state,
user: action.payload.user,
token: action.payload.user.token,
is_logged_in: true
}
break;
case APP_UNLOADED:
state = initialState
break;
case VARIFICATION_FAILED:
state = {
...state,
user: null,
}
break;
default:
state = { ...state };
break;
}
return state;
}
export default checkLogin;
在Saga.js中,我观察了每个appLoad操作,并按如下方式执行了操作
import { takeEvery, fork, put, all, call } from 'redux-saga/effects';
import { APP_LOAD } from './actionTypes';
import { appLoaded, tokenVerificationFailed } from './actions';
import { unsetLoggeedInUser } from '../../helpers/authUtils';
import agent from '../agent';
function* checkLogin({ payload: { token, history } }) {
try {
let response = yield call(agent.Auth.current, token);
yield put(appLoaded(response));
} catch (error) {
if (error.message) {
unsetLoggeedInUser();
yield put(tokenVerificationFailed());
history.push('/login');
} else if (error.response.text === 'Unauthorized') {
unsetLoggeedInUser();
yield put(tokenVerificationFailed());
}
}
}
export function* watchUserLogin() {
yield takeEvery(APP_LOAD, checkLogin)
}
function* commonSaga() {
yield all([fork(watchUserLogin)]);
}
export default commonSaga;
之后,对于productLists页面,我的代码如下
//importing part
class EcommerceProductEdit extends Component {
constructor(props) {
super(props);
this.state = {}
}
componentDidMount() {
**//seeing the props changes**
console.log(this.props);
this.props.activateAuthLayout();
if (this.props.user !== null && this.props.user.shop_id)
this.props.onLoad({
payload: Promise.all([
agent.Products.get(this.props.user),
])
});
}
render() {
return (
// JSX code removed for making code shorter
);
}
}
const mapStatetoProps = state => {
const { user, is_logged_in } = state.Common;
const { products } = state.Products.products.then(products => {
return products;
});
return { user, is_logged_in, products };
}
export default connect(mapStatetoProps, { activateAuthLayout, onLoad })(EcommerceProductEdit);
但在componentDidMount的这个页面中,如果我记录道具,我会在控制台中得到三次。如下
休息,一切都很好。我只是担心,我正在做的代码不符合标准。任何类型的见解都是高度赞赏的。谢谢
发布于 2020-06-26 12:25:57
这是因为你有三个状态更新,不能批量渲染。
首先在没有数据的情况下渲染。您可以在第一个日志中看到这一点。没有用户,他们也没有登录。然后你就会得到一个用户。您可以在第二个日志中看到这一点。有一个用户,但他们没有登录。然后你让他们登录。您可以在第三个日志中看到这一点。有一个用户,他们已经登录了。
如果所有这些都是在单独的步骤中完成的,并在每个步骤中更新Redux存储,那么您将在每个步骤之间渲染。但是,如果您获得了用户,并将他们登录,然后在同一时间范围内以redux状态存储他们,那么您只会呈现额外的时间。请记住,React和Redux是高度异步的库,它们试图使用批处理来确保在同一时间框架内完成的事情只会导致一次渲染,但有时您需要同时处理多个网络步骤。所以你没有做错任何事,你只是有很多步骤不能很容易地放在同一个框架中,因为它们依赖于一些外部资源,这些资源有自己的异步获取。
https://stackoverflow.com/questions/62594619
复制