我有一个reactjs项目,并且我有一个屏幕,该屏幕需要一个组件来在每次动作触发时显示更新的reducer值。我单击了按钮,但是没有发出提交按钮,而是使用了onclick事件,该事件发出了调度程序来触发操作。我看到减速器正在更新,但没有看到组件在屏幕上得到更新。在reducer更新后,如何触发render方法触发?在部分页面刷新的情况下,如果我只希望组件更新而不是render方法中的所有内容,该怎么办?
答案 0 :(得分:0)
组件只能在其道具改变或状态改变时更新。
如果将组件连接到正在更新的道具,则如果道具更改了组件的某些内容,它将重新渲染。
如果新道具没有更改组件的某些内容,则无需重新渲染任何东西。
This section from the docs对IMO很有帮助!
答案 1 :(得分:0)
无论何时分派触发任何事件的动作,都根据您在reducer中的需要创建一个变量(例如loading),将其设置为true或false,然后可以从mapStateToProps中访问道具。在获取新数据时,您将在componentWillReceiveProps方法上收到道具,您可以在其中有条件地检查属性(我们的案例加载)以在浏览器上呈现所需的DOM元素。
示例:根据服务器中的错误显示警报。
// import here
class Login extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
email: {
value:'',
isValid:false,
isTouched:false,
error:'Valid Email is required'
},
password:{
value:'',
isValid:false,
isTouched:false,
error:'Password of at least 6 character is Required'
},
isFormValid: false,
serverResp:'',
};
}
componentDidMount() {
// console.log("login props", this.props)
if (this.props.auth.isAuthenticated) {
this.props.history.push('/dashboard');
}
}
componentWillReceiveProps(nextProps) {
// console.log("Component will receive", nextProps);
if (nextProps.auth.isAuthenticated) {
return this.props.history.push('/dashboard');
}
//checking server error response
if (nextProps.auth.error) {
this.setState({ serverResp:nextProps.auth.error.message});
}
}
onChange = (e) => {
this.handleUserInput(e)
}
handleUserInput(e) {
const name = e.target.name;
const value = e.target.value;
let fieldState = this.state[name];
this.setState({[name]:{...fieldState,value:value,isTouched:true} },
() => { this.validateField(name, value) });
}
validateField(fieldName, value) {
//validation here
}
validateForm() {
this.setState({ isFormValid:this.state.email.isValid && this.state.password.isValid });
}
errorClass(error) {
return (error.length === 0 ? '' : 'has-error');
}
onSubmit = (e) => {
e.preventDefault();
if(this.state.isFormValid){
this.props.login({
email: this.state.email.value,
password: this.state.password.value
});
} else{
let emailState = this.state.email;
emailState = {...emailState,isTouched:true}
let passwordState = this.state.password;
passwordState = {...passwordState,isTouched:true}
this.setState({email:emailState,password:passwordState});
}
}
render() {
return (
<div className="app flex-row align-items-center">
<Container>
<Row className="justify-content-center">
<Col md="8">
<CardGroup>
<Card className="p-4">
<CardBody>
{ this.state.serverResp &&
<Alert color="danger">{this.state.serverResp}</Alert>
}<Form onSubmit={this.onSubmit}>
<h1>Login</h1>
<p className="text-muted">Sign In to your account</p>
<InputGroup className="mb-3">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="icon-user"></i>
</InputGroupText>
</InputGroupAddon>
<Input invalid={ this.state.email.isTouched && !this.state.email.isValid} type="text" name="email" value={this.state.email.value} placeholder="Username" onChange={this.onChange} autoComplete="username" />
<FormFeedback>{this.state.email.error}</FormFeedback>
</InputGroup>
<InputGroup className="mb-4">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="icon-lock"></i>
</InputGroupText>
</InputGroupAddon>
<Input invalid={this.state.password.isTouched && !this.state.password.isValid} type="password" name="password" value={this.state.password.value} placeholder="Password" onChange={this.onChange} autoComplete="current-password" />
<FormFeedback>{this.state.password.error}</FormFeedback>
</InputGroup>
<Row>
<Col xs="6">
<Button color="primary" className="px-4">Login</Button>
</Col>
<Link to="/forgotpassword">
<Col xs="6" className="text-right">
<Button color="link" className="px-0">Forgot password?</Button>
</Col>
</Link>
</Row>
</Form>
</CardBody>
</Card>
<Card className="text-white bg-primary py-5 d-md-down-none" style={{ width: '44%' }}>
<CardBody className="text-center">
<div>
<h2>Sign up</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua.</p>
<Link to="/signup">
<Button color="primary" className="mt-3" active tabIndex={-1}>Register Now!</Button>
</Link>
</div>
</CardBody>
</Card>
</CardGroup>
</Col>
</Row>
</Container>
</div>
);
}
}
// Login.propTypes = {
// loginUser: PropTypes.func.isRequired,
// auth: PropTypes.object.isRequired,
// errors: PropTypes.object.isRequired
// };
const mapStateToProps = state => ({
auth: state.login,
});
const mapDispatchToProps = dispatch =>{
return {
login:(userData) => login(userData,dispatch)
}
};
export default connect(mapStateToProps, mapDispatchToProps)(Login)