redux 状态更新缓慢
Slow state update in redux
所以我遇到了变量更新比路由更改慢的问题。
例如,当我的注册视图出现错误时,该错误会立即显示出来。当按返回返回登录视图时,错误正在通过操作重置 (在 componentWillUnmount 上触发操作 "clearErrors") 为空字符串。问题是在收到新的空错误状态之前,我可以在登录时看到错误消息一小会儿。
ErrorReducer.js
import {
ERROR,
CLR_ERROR
} from '../actions/types';
const INIT_STATE = {
error: ''
};
export default (state = INIT_STATE, action) => {
switch (action.type) {
case ERROR:
return { ...state, error: action.payload };
case CLR_ERROR:
return { ...state, error: '' };
default:
return state;
}
};
error.js(操作)
import { CLR_ERROR } from './types';
export const clearErrors = () => {
return (dispatch) => {
dispatch({ type: CLR_ERROR });
};
};
LoginForm.js
import React, { Component } from 'react';
import { View } from 'react-native';
import { Actions } from 'react-native-router-flux';
import { connect } from 'react-redux';
import { emailChanged, passwordChanged, loginUser, resetRoute, autoLogin } from '../actions';
import { Button, Input, Message } from './common';
class LoginForm extends Component {
componentWillUnmount() {
this.props.resetRoute();
}
onEmailChange(text) {
this.props.emailChanged(text);
}
onPasswordChange(text) {
this.props.passwordChanged(text);
}
onButtonPress() {
this.props.loading = true;
const { email, password } = this.props;
this.props.loginUser({ email, password });
}
render() {
return (
<View
style={{
flex: 1,
marginLeft: 10,
marginRight: 10,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
}}
keyboardShouldPersistTaps="always"
keyboardDismissMode="on-drag"
>
<Message
type="danger"
message={this.props.error}
/>
<Input
placeholder="din@email.se"
keyboardType="email-address"
returnKeyType="next"
onChangeText={this.onEmailChange.bind(this)}
value={this.props.email}
icon="ios-mail"
/>
<Input
secureTextEntry
placeholder="ditt lösenord"
onChangeText={this.onPasswordChange.bind(this)}
value={this.props.password}
icon="ios-key"
iconSize={22}
/>
<Button
loading={this.props.loading}
uppercase
color="primary"
label="Logga in"
onPress={this.onButtonPress.bind(this)}
/>
<Button
fontColor="primary"
label="Registrera"
onPress={() => Actions.register()}
/>
<Button
fontColor="primary"
label="Glömt lösenord"
onPress={() => Actions.resetpw()}
/>
</View>
);
}
}
const mapStateToProps = ({ auth, errors }) => {
const { email, password, loading, token } = auth;
const { error } = errors;
return { email, password, error, loading, token };
};
export default connect(mapStateToProps, {
emailChanged, passwordChanged, loginUser, resetRoute, autoLogin
})(LoginForm);
Message.js(显示错误的组件)
import React from 'react';
import { View, Text } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { colors } from '../style';
export const Message = ({ type, message }) => {
const style = {
view: {
alignSelf: 'stretch',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
margin: 15,
backgroundColor: colors[type],
borderRadius: 3,
elevation: 5,
shadowRadius: 5,
shadowColor: colors.smoothBlack,
shadowOffset: { width: 2.5, height: 2.5 },
shadowOpacity: 0.5
},
text: {
color: colors.alternative,
fontSize: 12,
alignSelf: 'center',
flex: 1
},
icon: {
marginRight: 20,
marginLeft: 0,
marginTop: 2,
alignSelf: 'center'
}
};
const getIcon = (iconType) => {
switch (iconType) {
case 'info':
return 'ios-information-circle';
case 'success':
return 'ios-checkmark-circle';
case 'danger':
return 'ios-alert';
case 'warning':
return 'ios-warning';
default:
return;
}
};
if (message.length > 0) {
return (
<View style={style.view}>
{(type) ? <Icon name={getIcon(type)} size={20} style={style.icon} /> : null}
<Text style={style.text}>{message}</Text>
</View>
);
}
return <View />;
};
我 运行 在设备 OnePlus3 上,所有 console.logs 已删除,生产版本。
根据我的阅读,这应该很快。我是不是做错了什么?
如果不看你的渲染代码是不可能说的,但很可能缓慢不是因为 redux 更新状态所花费的时间,而是 React 重新渲染 UI调度完成后 - 可能是因为它在您的导航器转换时正忙于重新渲染其他内容。
为了保证 redux-thunk
的动作顺序,您可以 return 来自您的 thunk 动作创建者的 Promise 并等待返回,直到动作被调度:
export const clearErrors = () => {
return (dispatch) => {
return new Promise(dispatch({ type: CLR_ERROR }));
};
};
那么在您看来,一旦错误被清除,您就可以执行返回导航操作:
// assuming the action creator has been passed
// to the component as props
this.props.clearErrors().then(() => navigator.back());
所以我遇到了变量更新比路由更改慢的问题。 例如,当我的注册视图出现错误时,该错误会立即显示出来。当按返回返回登录视图时,错误正在通过操作重置 (在 componentWillUnmount 上触发操作 "clearErrors") 为空字符串。问题是在收到新的空错误状态之前,我可以在登录时看到错误消息一小会儿。
ErrorReducer.js
import {
ERROR,
CLR_ERROR
} from '../actions/types';
const INIT_STATE = {
error: ''
};
export default (state = INIT_STATE, action) => {
switch (action.type) {
case ERROR:
return { ...state, error: action.payload };
case CLR_ERROR:
return { ...state, error: '' };
default:
return state;
}
};
error.js(操作)
import { CLR_ERROR } from './types';
export const clearErrors = () => {
return (dispatch) => {
dispatch({ type: CLR_ERROR });
};
};
LoginForm.js
import React, { Component } from 'react';
import { View } from 'react-native';
import { Actions } from 'react-native-router-flux';
import { connect } from 'react-redux';
import { emailChanged, passwordChanged, loginUser, resetRoute, autoLogin } from '../actions';
import { Button, Input, Message } from './common';
class LoginForm extends Component {
componentWillUnmount() {
this.props.resetRoute();
}
onEmailChange(text) {
this.props.emailChanged(text);
}
onPasswordChange(text) {
this.props.passwordChanged(text);
}
onButtonPress() {
this.props.loading = true;
const { email, password } = this.props;
this.props.loginUser({ email, password });
}
render() {
return (
<View
style={{
flex: 1,
marginLeft: 10,
marginRight: 10,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
}}
keyboardShouldPersistTaps="always"
keyboardDismissMode="on-drag"
>
<Message
type="danger"
message={this.props.error}
/>
<Input
placeholder="din@email.se"
keyboardType="email-address"
returnKeyType="next"
onChangeText={this.onEmailChange.bind(this)}
value={this.props.email}
icon="ios-mail"
/>
<Input
secureTextEntry
placeholder="ditt lösenord"
onChangeText={this.onPasswordChange.bind(this)}
value={this.props.password}
icon="ios-key"
iconSize={22}
/>
<Button
loading={this.props.loading}
uppercase
color="primary"
label="Logga in"
onPress={this.onButtonPress.bind(this)}
/>
<Button
fontColor="primary"
label="Registrera"
onPress={() => Actions.register()}
/>
<Button
fontColor="primary"
label="Glömt lösenord"
onPress={() => Actions.resetpw()}
/>
</View>
);
}
}
const mapStateToProps = ({ auth, errors }) => {
const { email, password, loading, token } = auth;
const { error } = errors;
return { email, password, error, loading, token };
};
export default connect(mapStateToProps, {
emailChanged, passwordChanged, loginUser, resetRoute, autoLogin
})(LoginForm);
Message.js(显示错误的组件)
import React from 'react';
import { View, Text } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { colors } from '../style';
export const Message = ({ type, message }) => {
const style = {
view: {
alignSelf: 'stretch',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
margin: 15,
backgroundColor: colors[type],
borderRadius: 3,
elevation: 5,
shadowRadius: 5,
shadowColor: colors.smoothBlack,
shadowOffset: { width: 2.5, height: 2.5 },
shadowOpacity: 0.5
},
text: {
color: colors.alternative,
fontSize: 12,
alignSelf: 'center',
flex: 1
},
icon: {
marginRight: 20,
marginLeft: 0,
marginTop: 2,
alignSelf: 'center'
}
};
const getIcon = (iconType) => {
switch (iconType) {
case 'info':
return 'ios-information-circle';
case 'success':
return 'ios-checkmark-circle';
case 'danger':
return 'ios-alert';
case 'warning':
return 'ios-warning';
default:
return;
}
};
if (message.length > 0) {
return (
<View style={style.view}>
{(type) ? <Icon name={getIcon(type)} size={20} style={style.icon} /> : null}
<Text style={style.text}>{message}</Text>
</View>
);
}
return <View />;
};
我 运行 在设备 OnePlus3 上,所有 console.logs 已删除,生产版本。
根据我的阅读,这应该很快。我是不是做错了什么?
如果不看你的渲染代码是不可能说的,但很可能缓慢不是因为 redux 更新状态所花费的时间,而是 React 重新渲染 UI调度完成后 - 可能是因为它在您的导航器转换时正忙于重新渲染其他内容。
为了保证 redux-thunk
的动作顺序,您可以 return 来自您的 thunk 动作创建者的 Promise 并等待返回,直到动作被调度:
export const clearErrors = () => {
return (dispatch) => {
return new Promise(dispatch({ type: CLR_ERROR }));
};
};
那么在您看来,一旦错误被清除,您就可以执行返回导航操作:
// assuming the action creator has been passed
// to the component as props
this.props.clearErrors().then(() => navigator.back());