- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Redux 开发 React Native 应用程序。
该应用程序有一个简单表单的注册屏幕:
import React from 'react';
import {
Alert,
Button,
KeyboardAvoidingView,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View
} from 'react-native';
import {connect} from "react-redux";
import {register} from "../redux/actions/Registration";
import {REGISTER} from "../redux/constants/ActionTypes";
import Loader from "./Loader";
const mapStateToProps = (state, ownProps) => {
return {
isLoggedIn: state.registration.isLoggedIn,
token: state.registration.token,
isLoading: state.common.isLoading,
error: state.common.error
};
};
const mapDispatchToProps = (dispatch) => {
return {
onRegister: (username, password, firstName, lastName) => {
dispatch(register(username, password, firstName, lastName));
}
}
};
@connect(mapStateToProps, mapDispatchToProps)
export default class RegistrationForm extends React.Component {
constructor(props) {
super(props);
this.state = {
route: REGISTER,
email: '',
password: '',
firstName: '',
lastName: '',
isLoading: false
}
}
register(e) {
this.props.onRegister(
this.state.email,
this.state.password,
this.state.firstName,
this.state.lastName
);
e.preventDefault();
}
componentDidUpdate() {
if (this.props.error != null && this.props.error !== undefined && this.props.error !== '') {
setTimeout(() => Alert.alert(this.props.error), 600);
}
}
render() {
const {isLoading} = this.props;
return (
<View style={styles.container}>
<KeyboardAvoidingView style={styles.registration_form} behaviour="padding">
<Loader loading={isLoading}/>
<TextInput style={styles.text_input} placeholder="First Name" placeholderTextColor="white"
underlineColorAndroid={'transparent'}
onChangeText={(text) => this.setState({firstName: text})}/>
<TextInput style={styles.text_input} placeholder="Last Name" placeholderTextColor="white"
underlineColorAndroid={'transparent'}
onChangeText={(text) => this.setState({lastName: text})}/>
<TextInput style={styles.text_input} placeholder="Email" placeholderTextColor="white"
underlineColorAndroid={'transparent'} keyboardType="email-address"
onChangeText={(text) => this.setState({email: text})}/>
<TextInput style={styles.text_input} placeholder="Password" placeholderTextColor="white"
underlineColorAndroid={'transparent'}
onChangeText={(text) => this.setState({password: text})}
secureTextEntry={true}/>
<TouchableOpacity style={styles.button} onPress={(e) => this.register(e)}>
<Text style={styles.btn_text}>Sign up</Text>
</TouchableOpacity>
<Button buttonStyle={{marginTop: 40}}
backgroundColor="transparent"
textStyle={{color: "#fff"}}
title="Login"
onPress={() => this.props.navigation.navigate('Login')}/>
</KeyboardAvoidingView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#36485f',
paddingLeft: 60,
paddingRight: 60
},
registration_form: {
alignSelf: 'stretch',
},
text_input: {
alignSelf: 'stretch',
height: 40,
marginBottom: 30,
color: '#fff',
borderBottomColor: '#f8f8f8',
borderBottomWidth: 1
},
button: {
alignSelf: 'stretch',
alignItems: 'center',
padding: 20,
backgroundColor: '#59cbbd',
marginTop: 30
},
btn_text: {
color: '#fff',
fontWeight: 'bold'
}
});
此外,我还创建了操作:
1) Common.js
import {FAILED, LOADING} from "../constants/ActionTypes";
export const loading = (isLoading) => {
return {
type: LOADING,
isLoading: isLoading
}
};
export const failed = (error) => {
return {
type: FAILED,
error: error
}
};
2) Registration.js
:
import {userService} from "../../service/UserService";
import {REGISTER} from "../constants/ActionTypes";
import {failed, loading} from "./Common";
export const register = (username, password, firstName, lastName) => {
return dispatch => {
dispatch(loading(true));
userService.register(username, password, firstName, lastName)
.then(resp => {
dispatch(loading(false));
dispatch({
type: REGISTER,
token: resp.json().token,
error: null
});
}
)
.catch(err => {
dispatch(loading(false));
dispatch(failed(err.message))
})
};
};
和 reducer :
1) Common.js
:
import {FAILED, LOADING, REGISTER} from "../constants/ActionTypes";
const defaultState = {
isLoading: false,
error: null
};
export default function reducer(state = defaultState, action) {
console.log('COMMON STATE: ', state);
console.log('COMMON ACTION: ', action);
switch (action.type) {
case LOADING:
return {
... state,
isLoading: action.isLoading
};
case FAILED:
return {
... state,
error: action.error
};
default:
return state;
}
}
2) Registration.js
:
import {FAILED, LOADING, REGISTER} from "../constants/ActionTypes";
const defaultState = {
isLoggedIn: false,
token: null
};
export default function reducer(state = defaultState, action) {
console.log('REGISTER STATE: ', state);
console.log('REGISTER ACTION: ', action);
switch (action.type) {
case REGISTER:
return Object.assign({}, state, {
isLoggedIn: action.isLoggedIn,
token: action.token
});
default:
return state;
}
}
3) Index.js
:
import { combineReducers } from 'redux';
import registration from './Registration';
import login from './Login';
import common from './Common'
const rootReducer = combineReducers({
registration,
login,
common
});
export default rootReducer;
当我第一次单击注册组件上的“注册”按钮时 - 一切正常 - 它会显示一个微调器,然后显示一个警报。
当我第二次(或第三次等)单击“注册”按钮时,它还会显示一个微调器,然后一个接一个地打开两个警报。
我期望的是:每次点击应用程序应该只显示一个警报。
在控制台中我看到以下输出:
10:27:07 PM: REGISTER STATE: Object {
10:27:07 PM: "isLoggedIn": false,
10:27:07 PM: "token": null,
10:27:07 PM: }
10:27:07 PM: REGISTER ACTION: Object {
10:27:07 PM: "isLoading": false,
10:27:07 PM: "type": "LOADING",
10:27:07 PM: }
10:27:07 PM: LOGIN STATE: Object {
10:27:07 PM: "isLoggedIn": false,
10:27:07 PM: "token": null,
10:27:07 PM: }
10:27:07 PM: LOGIN ACTION: Object {
10:27:07 PM: "isLoading": false,
10:27:07 PM: "type": "LOADING",
10:27:07 PM: }
10:27:07 PM: COMMON STATE: Object {
10:27:07 PM: "error": "Network request failed",
10:27:07 PM: "isLoading": true,
10:27:07 PM: }
10:27:07 PM: COMMON ACTION: Object {
10:27:07 PM: "isLoading": false,
10:27:07 PM: "type": "LOADING",
10:27:07 PM: }
10:27:07 PM: REGISTER STATE: Object {
10:27:07 PM: "isLoggedIn": false,
10:27:07 PM: "token": null,
10:27:07 PM: }
10:27:07 PM: REGISTER ACTION: Object {
10:27:07 PM: "error": "Network request failed",
10:27:07 PM: "type": "FAILED",
10:27:07 PM: }
10:27:07 PM: LOGIN STATE: Object {
10:27:07 PM: "isLoggedIn": false,
10:27:07 PM: "token": null,
10:27:07 PM: }
10:27:07 PM: LOGIN ACTION: Object {
10:27:07 PM: "error": "Network request failed",
10:27:07 PM: "type": "FAILED",
10:27:07 PM: }
10:27:07 PM: COMMON STATE: Object {
10:27:07 PM: "error": "Network request failed",
10:27:07 PM: "isLoading": false,
10:27:07 PM: }
10:27:07 PM: COMMON ACTION: Object {
10:27:07 PM: "error": "Network request failed",
10:27:07 PM: "type": "FAILED",
10:27:07 PM: }
所以 reducer 被调用了两次。如何解决这个问题?或者如何防止打开第二个警报弹出窗口?
更新。
您可以在 GitHub 上找到该项目的源代码:https://github.com/YashchenkoN/money-observer-client
更新 2.从@Chase DeAnda 更改后,它看起来像这样:
最佳答案
在 register
函数中,您需要检查 props
以确定用户是否已经注册:
register(e) {
e.preventDefault();
if (!this.props.token) {
this.props.onRegister(
this.state.email,
this.state.password,
this.state.firstName,
this.state.lastName
);
} else {
// User already registered
// Redirect to login page
}
}
编辑
好的,我想我现在明白问题所在了。您正在使用 componentDidUpdate
生命周期方法。 每次一个状态或 Prop 被传递给它时,这个方法被调用,不一定只有当它们发生变化时。您遇到的问题是您没有检查 this.props.error
是否实际上不同于您已经显示的第一个错误。将其更改为:
componentDidUpdate(prevProps,prevState) {
if(prevProps.error !== this.props.error && this.props.error){
setTimeout(() => Alert.alert(this.props.error), 600);
}
}
由于您有多个 reducer 对失败的 XHR 请求使用react,您的组件将从多个操作中获得传递给它的 Prop 。您需要确保仅在错误与之前传入的错误不同时才显示错误。
关于javascript - Redux reducer 被调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49521018/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!