基于状态的条件渲染不适用于状态更改

时间:2019-10-19 19:23:10

标签: react-native

我的状态值会随着Switch的变化而变化。根据该状态项的值,我想更改按钮的样式。我可以看到状态发生了变化,但是颜色没有变化。

这似乎很简单,如本文档所示:https://reactjs.org/docs/conditional-rendering.html

我实际上在同一条语句中有一个条件渲染,但是它引用的是redux状态而不是组件状态。

我在下面包括了代码的相关方面,并试图去除不必要的内容。

还是有点长。

/* eslint-disable prettier/prettier */
import React, { Component } from 'react';
import {
    View,
    Text,
    TouchableOpacity,
    Dimensions,
    StyleSheet,
    TextInput,
    Switch,
    ActivityIndicator,
} from 'react-native';
import { connect } from 'react-redux';

// Actions
import { createUser } from '../../actions/user-actions';

// Getting dims
const { width: WIDTH } = Dimensions.get('window');

// Styling
const styles = StyleSheet.create({
    containerStyle: {
        flex: 1,
        backgroundColor: 'black',
        alignItems: 'center',
        justifyContent: 'center',
    },
    footerContainerStyle: {
        justifyContent: 'flex-start',
        flex: 3,
        width: WIDTH,
        paddingHorizontal: 30,
        alignItems: 'center',
        marginTop: 45,
    },
    tcStyle: {
        flexDirection: 'row',
        marginBottom: 20,
    },
    switchStyle: {
        marginRight: 15,
    },
    buttonStyle: {
        width: WIDTH-100,
        height: 50,
        backgroundColor: '#007AFF',
        borderRadius: 4,
        alignItems: 'center',
        justifyContent: 'center',
        marginBottom: 20,
    },
    disabledButtonStyle: {
        width: WIDTH-100,
        height: 50,
        backgroundColor: '#007AFF',
        borderRadius: 4,
        alignItems: 'center',
        justifyContent: 'center',
        marginBottom: 20,
        opacity: 0.3,
    },
    buttonTextStyle: {
        color: 'white',
        fontSize: 14,
        fontWeight: 'bold',
    },
    linkStyle: {
        textDecorationLine: 'underline',
        color: 'blue',
    },
});

// Component
class Signup extends Component {
    constructor(props) {
        super(props);
        this.state = {
            switchValue: false,
            email: '',
            name: '',
            password: '',
            passwordConfirm: '',
            errorMessage: '',
        };
    }

    componentDidUpdate() {
        console.log(this.props.users);
        const { navigation } = this.props;
        if (this.props.users.user) {
            navigation.navigate('Home');
        }
    }

    componentDidMount() {
        console.log(this.props);
    }

    // Helper functions
    toggleSwitch = (value) => {
        this.setState({switchValue: value});
    };

    onSignUp = () => {
        const { email, name, password, passwordConfirm, switchValue } = this.state;

        const { createUser } = this.props;

        if (password !== passwordConfirm) {
            console.log('Passwords do not match')
            this.setState({errorMessage: 'Passwords do not match'});
            return;
        }

        if (!switchValue) {
            console.log('You must agree to terms');
            this.setState({errorMessage: 'You must agree to terms'});
            return;
        }

        createUser(email, password, name);
    }

    render() {
        // Conditional button rendering
        const { email, password, passwordConfirm, name, switchValue } = this.state;
        let button;
        console.log(switchValue);

        if (this.props.users.loading) {
            button = (
                <TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
                    <ActivityIndicator size="large" />
                </TouchableOpacity>
            );
        } else if (switchValue) {
            button = (
                <TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
                    <Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
                </TouchableOpacity>
            )
        } else if (!switchValue) {
            button = (
                <TouchableOpacity style={[styles.disabledButtonStyle]} onPress={this.onSignUp}>
                    <Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
                </TouchableOpacity>
            )
        }

        return (
            <View style={styles.containerStyle}>
                <View style={styles.footerContainerStyle}>
                    <View style={styles.tcStyle}>
                        <Switch
                            onValueChange = {this.toggleSwitch}
                            value = {this.state.switchValue}
                            style = {styles.switchStyle}
                            trackColor={{true: '#007AFF', false: 'grey'}}
                        />
                        <Text style={{color: 'white', flexWrap: 'wrap', flex: 1}}>I have read & agree to the <Text style={styles.linkStyle}>Terms of Use</Text> and <Text style={styles.linkStyle}>Privacy Policy</Text></Text>
                    </View>

                    {button}

                    <View style={styles.textLinkStyle}>
                        <Text style={styles.ctaHelpTextStyle}>Have an account?</Text>
                        <TouchableOpacity>
                            <Text style={styles.ctaTextStyle}> Sign In</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            </View>
        );
    }
}

// state mapping
const mapStateToProps = ({ users }) => ({
    users,
});

// Export
export default connect(mapStateToProps, {
    createUser,
})(Signup);

如果我切换那个开关,我期望按钮组件会变成另一种样式。不过,这没有发生。

3 个答案:

答案 0 :(得分:1)

实际上,您的状态可以正确更改,但是不透明度不起作用。

更新:

似乎本机反应存在问题,从而改变了TouchableOpacity的不透明度。

一种解决方案是从样式中消除不透明度。并用View组件包装TouchableOpacity组件,使View变得不透明。

您可以尝试这样:

 else if (switchValue) {
      button = (
        <View opacity={0.5}>
          <TouchableOpacity style={styles.buttonStyle} onPress={this.onSignUp}>
            <Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT true</Text>
          </TouchableOpacity>
        </View>
      );
    } else if (!switchValue) {
      button = (
        <View opacity={0.1}>
          <TouchableOpacity
            style={styles.disabledButtonStyle}
            onPress={this.onSignUp}
          >
            <Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT false</Text>
          </TouchableOpacity>
        </View>
      );

答案 1 :(得分:0)

例如添加条件中的回报

if (this.props.users.loading) {
      return(
         <TouchableOpacity style={[styles.buttonStyle]} onPress{this.onSignUp}>
            <ActivityIndicator size="large" />
        </TouchableOpacity>
   );
  }

答案 2 :(得分:0)

根据您的代码,两个按钮之间的唯一区别只是样式。 我要采用的方法只是使样式自身内部的条件不是render方法本身的if语句,请遵循:


解决方案

修改此片段:

// ... Other code parts

if (this.props.users.loading) {
    button = (
        <TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
            <ActivityIndicator size="large" />
        </TouchableOpacity>
    );
} else if (switchValue) {
    button = (
        <TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
            <Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
        </TouchableOpacity>
    )
} else if (!switchValue) {
    button = (
        <TouchableOpacity style={[styles.disabledButtonStyle]} onPress={this.onSignUp}>
            <Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
        </TouchableOpacity>
    )
}

对此:

// ... Other code parts

if (this.props.users.loading) {
    button = (
        <TouchableOpacity style={[styles.buttonStyle]} onPress={this.onSignUp}>
            <ActivityIndicator size="large" />
        </TouchableOpacity>
    );
} else {
    button = (
        <TouchableOpacity style={switchValue ? styles.buttonStyle : styles.disabledButtonStyle} onPress={this.onSignUp}>
            <Text style={styles.buttonTextStyle}>CREATE AN ACCOUNT</Text>
        </TouchableOpacity>
    )
}

希望这会有所帮助!