reactjs:每次更换减速器时都重新渲染屏幕的一部分

时间:2018-12-29 00:50:00

标签: javascript reactjs redux

我有一个reactjs项目,并且我有一个屏幕,该屏幕需要一个组件来在每次动作触发时显示更新的reducer值。我单击了按钮,但是没有发出提交按钮,而是使用了onclick事件,该事件发出了调度程序来触发操作。我看到减速器正在更新,但没有看到组件在屏幕上得到更新。在reducer更新后,如何触发render方法触发?在部分页面刷新的情况下,如果我只希望组件更新而不是render方法中的所有内容,该怎么办?

2 个答案:

答案 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)