我有以下组件,每次尝试使用setState
函数时都会收到警告:
Warning: setState(...): Can only update a mounted or mounting component.
This usually means you called setState() on an unmounted component.
This is a no-op. Please check the code for the LoginView component
我尝试添加componentDidMount
和componentWillUnmount
仅用于调试此问题,而在this.setState
回调中,状态已更新,我将mounted
视为真,当我尝试输入我的输入onInputChange
this.state.mounted
仍然是假的,并且不会更新状态......
我无法弄清楚我做错了什么,因为我试图在网上关注示例。
import React from 'react';
import { bindActionCreators } from 'redux'
import BaseComponent from 'BaseComponent';
import * as loginActions from './LoginActions';
import { connect } from 'react-redux'
const LOGIN_ACTIONS = loginActions.LOGIN_ACTIONS
class LoginView extends React.Component {
constructor(props){
super(props);
this.props = props;
this.setupState.bind(this);
this.onInputChange = this.onInputChange.bind(this);
this.state = this.setupState();
this.submitForm = this.submitForm.bind(this);
this.render = this.render.bind(this);
}
setupState (){
debugger;
return {
mounted: false,
fields : {
email: '',
password:'',
},
};
}
componentDidMount() {
debugger;
this.setState({ mounted: true }, function() {
debugger;
console.log(this);
}.bind(this));
}
componentWillUnmount() {
debugger;
this.setState({ mounted: false })
}
onInputChange(evt){
const fields = this.state.fields;
fields[evt.target.name] = evt.target.value;
if(this.state.mounted){
this.setState({fields : fields});
}
// this.state.fields = fields;
}
submitForm(evt){
evt.preventDefault();
//debugger;
//this.actions.login(this.state.fields.email, this.state.fields.password);
}
render() {
return (
<div>
<h1>Swirl Simulator Manager</h1>
<form onSubmit={this.submitForm}>
<label>Username</label>
<input type='text' placeholder='Email'
name='email'
value={this.state.fields.email}
onChange={this.onInputChange} />
<br />
<label>Password</label><input type='password'name='password' value={this.state.fields.password} onChange={this.onInputChange}/>
<br />
<input type="submit" />
</form>
</div>
)
}
}
export default connect(
state => { return { auth: state.auth }; },
dispatch => { return { actions: bindActionCreators(loginActions, dispatch) }; }
)(LoginView);
我能够通过在render函数中绑定它来使它工作,如下所示:
<input type='text' placeholder='Email'
name='email'
value={this.state.fields.email}
onChange={this.onInputChange.bind(this)} />
但我不明白为什么会这样,而this.onInputChange.bind(this)
在构造函数中并不是
我也尝试过使用箭头功能:
onInputChange = (evt) => {
const fields = this.state.fields;
fields[evt.target.name] = evt.target.value;
this.setState({fields : fields}, ()=> {
console.log(this.state);
});
}
这导致了与在构造函数
中完成的问题相同的问题import React from 'react';
import { bindActionCreators } from 'redux'
export default class LoginView extends React.Component {
state = {
fields : {
email: '',
password:'',
},
};
constructor(props){
debugger;
super(props);
//this.props = props;
//this.setupState.bind(this);
//this.render = this.render.bind(this);
// This doesn't allow me to set state in onInputChange
this.onInputChange = this.onInputChange.bind(this);
this.submitForm = this.submitForm.bind(this);
}
onInputChange(evt) {
evt.preventDefault();
const fields = this.state.fields;
fields[evt.target.name] = evt.target.value;
this.setState({fields : fields}, ()=> {
console.log(this.state);
});
}
/* This also does not allow me to setState
onInputChange = (evt) => {
evt.preventDefault();
const fields = this.state.fields;
fields[evt.target.name] = evt.target.value;
this.setState({fields : fields}, ()=> {
console.log(this.state);
});
}
*/
submitForm(evt){
evt.preventDefault();
console.log(this.state);
}
render() {
return (
<div>
<h1>Login</h1>
<form onSubmit={this.submitForm}>
<label>Username</label>
<input type='text' placeholder='Email'
name='email'
value={this.state.fields.email}
onChange={this.onInputChange} />
<br />
<label>Password</label>
<input type='password'
name='password'
value={this.state.fields.password}
onChange={this.onInputChange.bind(this)}/>
<br />
<input type="submit" />
</form>
</div>
)
}
}
如果我更改密码字段的输入,一切都按预期工作,但如果我使用构造函数来绑定它或者如果我使用箭头函数(两者都在上面注释掉),则从不在电子邮件上
以防这是由webpack引起的,这是我的webpack配置:
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractCSS = new ExtractTextPlugin('[name].bundle.css')
const config = {
context: path.resolve(__dirname, 'src'),
devtool: 'inline-source-map',
entry: {
'app' : [
'react-hot-loader/patch',
'./App.js'
]
},
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/build',
filename: '[name].bundle.js'
},
module: {
rules: [{
test: /\.jsx?$/,
include: path.resolve(__dirname, 'src'),
use: [{
loader: 'babel-loader',
options: {
presets: [
//'es2017',
'es2016',
"stage-0",
"react"
],
plugins:[
'react-hot-loader/babel'
]
}
}]
},
{
test: /\.scss$/,
include: /node_modules/,
loader: extractCSS.extract(['css-loader','sass-loader'])
}]
}, // End : module
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
extractCSS,
],
resolve: {
alias: {
components : path.resolve(__dirname, 'src/components'),
BaseComponent$ : path.resolve(__dirname, 'src/components/BaseComponent.js'),
'views' : path.resolve(__dirname, 'src/views'),
'modules' : path.resolve(__dirname, 'src/modules'),
'services' : path.resolve(__dirname, 'src/services')
}
}
}
module.exports = config
和我的依赖
"devDependencies": {
"babel-core": "6.24.0",
"babel-loader": "6.4.1",
"babel-preset-es2016": "6.22.0",
"babel-preset-es2017": "6.22.0",
"babel-preset-react": "6.23.0",
"babel-preset-stage-0": "6.22.0",
"css-loader": "0.27.3",
"extract-text-webpack-plugin": "2.1.0",
"node-sass": "4.5.1",
"redux-devtools-extension": "2.13.0",
"sass-loader": "6.0.3",
"webpack": "2.3.2",
"webpack-dev-server": "2.4.2"
},
"dependencies": {
"css-loader": "0.27.3",
"node-sass": "4.5.1",
"react": "15.4.2",
"react-dom": "15.4.2",
"react-hot-loader": "^3.0.0-beta.6",
"react-redux": "5.0.3",
"react-router-dom": "4.0.0",
"redux": "3.6.0",
"redux-thunk": "2.2.0",
"sass-loader": "6.0.3",
"style-loader": "0.16.0"
}
答案 0 :(得分:1)
不确定,但这些更改不是必需的,可能会解决您的问题:
1。删除以下行:
this.props = props;
this.setupState.bind(this);
this.render = this.render.bind(this); //binding of render method is not required
2。从setState
方法移除componentWillUnmount
,因为在setState
之后,React
将尝试执行re-rendering
componentWillUnmount() {
debugger;
// this.setState({ mounted: false })
}
根据DOC:
componentWillUnmount()在组件出现之前立即被调用 未安装和销毁。在此方法中执行任何必要的清理, 例如使计时器无效,取消网络请求。
答案 1 :(得分:0)
不确定您为什么要跟踪组件中的已装入或未装入状态。问题的根源基本上是这样的:
componentWillUnmount() {
this.setState({ mounted: false })
}
尝试设置一个组件的状态是没有意义的,这个组件的状态将不可避免地被反应卸载,所以你得到一个警告,你正在做的事情基本上是no-op
(没有操作)并且没有影响。我强烈建议你阅读component lifecycle并澄清你的意思