reactjs - 在 react/redux 应用程序中显示成功和错误消息
问题描述
我正在尝试向我的应用程序添加 toast 通知,我一直在尝试使用的一个插件是 react-toastify。
我遇到的问题可能更多的是一般的 react/redux 问题,而不是 react-toastify 之类的插件。
我正在使用 reducer 为错误和成功消息设置 redux 状态,根据我对当前代码的理解,每个错误或成功消息都在存储中持久存在,直到调用另一个操作来清除它们。
我无法弄清楚的问题是我如何只触发一次敬酒。例如。我输入了错误的凭据,它会创建一个错误的 toast,但是每当状态更改并重新加载(在电子邮件或密码字段中输入任何内容)时,它都会创建另一个 toast。
如何让它只显示一次?
userActions.js
function handleErrors(res) {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => {throw err;});
}
}
export const login = (user) => dispatch => {
fetch(`${url}/login`,
{
credentials: 'include',
method: 'post',
body: user,
headers: new Headers({
'Content-Type': 'application/json',
'Accept': 'application/json'
})
})
.then(handleErrors)
.then(res =>
dispatch({
type: LOGIN,
payload: res
})
)
.catch(error =>
dispatch({
type: ERROR,
payload: error
})
)
}
userReducer.js
const initialState = {
errors: '',
success: ''
};
export default function(state = initialState, action) {
switch (action.type) {
case LOGIN:
return {
...state,
errors: '',
success: action.payload.message
};
case ERROR:
return {
...state,
success: '',
errors: action.payload.message
}
default:
return state;
}
}
应用程序.js
app.post('/login', function(req, res) {
... return res.status(500).send({ message: 'Wrong credentials' });
... return res.status(200).send({ message: 'good!' });
});
登录.js
class Login extends React.Component {
constructor() {
super();
this.state = {
email: "",
password: ""
}
}
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
render() {
const { errors, login, success } = this.props;
if (success !== '') toast.success(success, {
position: toast.POSITION.TOP_CENTER
});
if (errors !== '') toast.error(errors, {
position: toast.POSITION.TOP_CENTER
});
return (
<div>
<input type="text" id="email" placeholder="Email Address" onChange={this.handleChange} />
<input type="password" id="password" placeholder="Password" onChange={this.handleChange} />
<button onClick={() => login(JSON.stringify({email: this.state.email, password: this.state.password}))}>Log In</button>
<ToastContainer />
</div>
)
}
}
const mapStateToProps = state => ({
errors: state.store.errors,
success: state.store.success
});
export default connect(mapStateToProps, {login})(Login);
解决方案
您在 render 中调用 toast.success 或 toast.error ,每次重新渲染组件时都会弹出一个新的 toast。
解决方案很简单。将你的 toast 调用移到渲染之外,它们只会被调用一次。
实现此目的的一种方法是从您的 userAction 返回一个值。
export const login = (user) => dispatch => {
return new Promise((resolve, reject) => {
fetch(`${url}/login`,
{
credentials: 'include',
method: 'post',
body: user,
headers: new Headers({
'Content-Type': 'application/json',
'Accept': 'application/json'
})
})
.then(handleErrors)
.then(res => {
dispatch({
type: LOGIN,
payload: res
})
resolve(res)
}
)
.catch(error => {
dispatch({
type: ERROR,
payload: error
})
reject(error)
}
)
}
}
然后使用该值在 login.js 中烤面包。
class Login ... {
...
loginUser = () => {
this.props.login(JSON.stringify({email: this.state.email, password: this.state.password}))
.then(res => {
toast.success(res.message, { position: toast.POSITION.TOP_CENTER })
}
).catch(error => {
toast.error(error.message, { position: toast.POSITION.TOP_CENTER })
}
)
}
...
render() {
return (
...
<button onClick={this.loginUser}>Log In</button>
...
)
}
}
还有其他方法可以实现相同的功能,并且根据项目的结构,您可能希望以更通用的方式敬酒。
推荐阅读
- javascript - jquery函数在表的第二页上不起作用
- c# - 在同一解决方案中找不到引用项目的类型或命名空间
- java - 在“docker run imagename”命令上按顺序(不是同时)运行多个 Jar 文件
- c++ - 在 C++ 中获取旋转的音高
- c++ - clang 插件:在编译期间修改 AST
- ruby-on-rails - Rails 添加 pass 变量以从循环创建新记录
- sql - 使用JPA在Sql中具有不同值的多个语句where子句
- oracle - LocalDateTime 映射到 Oracle DATE,但不映射到 H2 DATE
- c# - 在 C# 中将用户名转换为 SID
- cmake - 为什么 CMAKE 安装的目标无法链接到提供的库?