如何在复选框中设置选中的值

how to set checked value in checkbox

在下面的 React-native 代码中,我使用了 native-base 复选框来考虑函数 _checkBox()_checkbox_check() 我使用状态变量来保存值,无论它们是否在状态 cb{}

中被选中

按下复选框后,我可以更改我在 _checkbox_check() 函数中使用 console.log() 检查的值,但相同的值在 checked={this.state.cb[data.id]} 处不起作用,这意味着对应于复选框键的对象 cb 中的 true 和 false 存在,但是当它为 true 时,复选框被选中, 虽然我已经检查过提供像 checked={true} 这样的静态值,但它工作正常。

如果有错误或改进的机会,请提出建议 我整个页面的代码如下

import React from "react";
import AsyncStorage from "@react-native-community/async-storage";
import {
   Text,
   View,
   ScrollView,
   Platform,
   Image,
   TouchableOpacity,
   ToastAndroid,
   StatusBar
   } from "react-native";

     import {
       Content,
       Container,
       Button,
       Icon,
       Header,
       Left,
       Right,
       Body,
       Title,
       Item,
       Card,
       CardItem,
       DatePicker,
       Label,
       Input,
       ListItem,
       CheckBox
     } from "native-base";

     import Network from "../../network/network";
     import LinearGradient from "react-native-linear-gradient";
     import * as constant from "../../Constants/Constant";
     const deviceHeight = constant.deviceHeight;
     const deviceWidth = constant.deviceWidth;
     import styles from "./Styles";
     import Styles from "./Styles";

     const icn = "../../Images/icons/blue/";
     const platform = Platform.OS;

     export default class SignInScreen extends React.Component {
       constructor(props) {
         super(props);
         this.state = {
           services: null,
           poolId: null,
           chosenDate: new Date(),
           choice: null,
           description: null,
           val: true,
           cb: {}
         };

         this.setDate = this.setDate.bind(this);
       }
       setDate(newDate) {
         this.setState({ chosenDate: newDate });
       }

       async componentWillMount() {
         await Network.Token_get("apk/getServiceList", async response => {
           if (response.status == true) {
             await this.setState({
               services: response.serviceData
             });
           }
         });
       }
       componentDidMount() {
         const { navigation } = this.props;
         const itemId = navigation.getParam("id");
         this.setState({
           poolId: itemId
         });
       }
       render() {
         return (
           <Container>
             <Header
               style={{
                 borderBottomWidth: 0,
                justifyContent: "center",
                 alignItem: "center"
               }}
             >
               <Left>
                 <Button
                      transparent
                   onPress={() => {
                     this.props.navigation.openDrawer();
                   }}
                 >
                   <Icon name="menu" />
                 </Button>
               </Left>
               <Body>
                 <Title style={styles.title}>Service Details</Title>
               </Body>
               <Right>
                 <Button transparent onPress={() => this._signOutAsync()}>
                   <Icon name="log-out" />
                 </Button>
               </Right>
             </Header>
             <Content contentContainerStyle={styles.content} bounces={false}>
               <ScrollView
                 contentContainerStyle={{
                   padding: 10,
                   alignItems: "flex-start",
                   justifyContent: "center",
                   backgroundColor: "#ffff",
                   shadowColor: "#1C0C59",
                   shadowOffsetWidth: 3,
                   shadowOffsetHeight: 3,
                   shadowOpacity: 0.1,
                   shadowRadius: 3,
                   elevation: 3,
                   borderRadius: 7,
                   bgColor: "#ffffff"
                 }}
               >
                 <View
                   style={{ alignItems: "flex-start", justifyContent: "flex-start" }}
                 >
                   {this._checkBoxes()}
                 </View>

                 <View style={{ flexDirection: "row" }}>
                   <View>
                     <Text style={{ top: 10 }}>
                       Schedule Date:
                       {/* {this.state.chosenDate.toString().substr(4, 12)} */}
                     </Text>
                   </View>
                   <View>
                     <DatePicker
                       defaultDate={new Date(2018, 4, 4)}
                       minimumDate={new Date(2018, 1, 1)}
                       maximumDate={new Date(2018, 12, 31)}
                       locale={"en"}
                       timeZoneOffsetInMinutes={undefined}
                       modalTransparent={false}
                       animationType={"fade"}
                       androidMode={"default"}
                       placeHolderText="Select Schedule Date"
                       // textStyle={{ color: "green" }}
                       placeHolderTextStyle={{ color: "#d3d3d3" }}
                       onDateChange={this.setDate}
                       disabled={false}
                     />
                   </View>
                 </View>

                 <Item floatingLabel style={{ marginTop: 20, marginBottom: 50 }}>
                  <Label>Description</Label>
                  <Input
                     multiline={true}
                     //  style={{height:200, textColor: "#000"}}
                     style={{ color: "#000", height: 100 }}
                     onChangeText={description => this.setState({ description })}
                   />
                 </Item>

                 <Button
                   rounded
                   primary
                   onPress={() => this._submit()}
                   style={{ paddingLeft: 18, alignSelf: "center" }}
                 >
                   <Text style={{ fontWeight: "600", color: "#000"          }}>Submit</Text>
                   <Icon name="send" />
                 </Button>
               </ScrollView>
             </Content>
           </Container>
         );
       }

       mapPools(poolList) {
         if (poolList) {
           return poolList.map(data => {
             return (
               <Card style={{ borderRadius: 7 }}>
                 <CardItem style={{ borderRadius: 7 }}>
                   <TouchableOpacity>
                     <View style={styles.View_inside_card}>
                       <View style={styles.Incard_icon_View}>
                         <Image
                           source={require(icn + "swimmingPool.png")}
                           style={styles.Incard_icon}
                         />
                       </View>
                       <View style={styles.Incard_Detail_View}>
                         <Text style={styles.Detail_name}>{data.pool_title}</Text>
                         <Text style={styles.Detail_name}>{data.address}</Text>
                       </View>
                     </View>
                   </TouchableOpacity>
                 </CardItem>
               </Card>
             );
           });
         }
       }

       _signOutAsync = async () => {
         var loginid = await AsyncStorage.getItem("@LoginID");
         payload = {
           loginId: loginid
         };
         await Network.Token_put("apk/logout", payload, async response => {
           ToastAndroid.show(response.message, ToastAndroid.SHORT);
           if (response.status === true) {
             await AsyncStorage.clear();
             this.props.navigation.navigate("Auth");
           }
         });
         // await AsyncStorage.clear();
         // this.props.navigation.navigate("Auth");
       };




       _checkBoxes = () => {
         if (this.state.services) {
           return this.state.services.map(data => {
             return (
               <ListItem noBorder>
                 <CheckBox
                   checked={this.state.cb[data.id]}
                   onPress={() => this._chkbox_check(data.id)}
                 />
                 <Text style={{ marginLeft: 20 }}>{data.services_title}</Text>
               </ListItem>
             );
           });
         }
       };

       _chkbox_check = param => {
         console.log(param, this.state.cb);

         if (this.state.cb.hasOwnProperty(param)) {
           var element = this.state.cb[param];
           console.log(element);
           this.state.cb[param] = !element;
           element = this.state.cb[param];
           console.log(element);
         } else {
           this.state.cb[param] = true;
         }
       };

       _submit = async sd => {
         var payload = {
           pool_id: this.state.poolId,
           request_schedule_dateTime: this.state.chosenDate,
           request_details: this.state.description,
           service_type_id: this.state.choice
         };
         var url = "apk/createPoolRequest";

         console.log("payload=>", payload);

         await Network.Token_post(url, payload, async response => {
           ToastAndroid.show(response.message, ToastAndroid.SHORT);
           if (response.status === true) {
             this.props.navigation.pop();
           }
         });
       };
     }

修改组件状态时应使用setState

_chkbox_check = param => {
  if (this.state.cb.hasOwnProperty(param)) {
    var element = this.state.cb[param];
    this.setState({
      cb: {
        ...this.state.cb,
        [param]: !element,
      },
    });
  } else {
    this.setState({
      cb: {
        ...this.state.cb,
        [param]: true,
      },
    });
  }
}

根据文档,直接修改状态是一个很大的禁忌。原因有很多,但您 运行 遇到的问题是因为 render()setState() 被调用之前不会被触发。

在上面的代码中 setState 只会修改 cb 状态,但是由于您不想完全覆盖 cb (因为它存储了多个复选框的选中状态),您必须通过将 spread operator ..., and access the dynamic key 括在方括号 [].

中来与它合并

这是一个去除了所有不相关代码的工作示例:

import React from 'react';
import { View } from 'react-native';
import { ListItem, CheckBox } from 'native-base';

export default class SignInScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      cb: {}
    };
  }

  render() {
    return (
      <View>
        {this._checkBoxes()}
      </View>
    );
  }

  _checkBoxes = () => {
    const services = [
      { id: 'service1' },
      { id: 'service2' },
      { id: 'service3' },
    ];
    return services.map(data => {
      return (
        <ListItem noBorder>
          <CheckBox
            checked={this.state.cb[data.id]}
            onPress={() => this._chkbox_check(data.id)}
          />
        </ListItem>
      );
    });
  }

  _chkbox_check = param => {
    if (this.state.cb.hasOwnProperty(param)) {
      var element = this.state.cb[param];
      this.setState({
        cb: {
          ...this.state.cb,
          [param]: !element,
        },
      });
    } else {
      this.setState({
        cb: {
          ...this.state.cb,
          [param]: true,
        },
      });
    }
  }
}

如果您在 setState 中省略带有 ...this.state.cb 的行,则 cb 将被新值完全覆盖。

例如,假设您开始于:

state.cb = { service1: true }

然后调用_chkbox_check('service2');,你会得到:

state.cb = { service2: true }

但是使用展开运算符你会得到:

state.cb = { service1: true, service2: true }

旁注

您的 _chkbox_check 函数可以通过不检查状态中的 属性 来简化:

_chkbox_check = param => {
  this.setState({
    cb: {
      ...this.state.cb,
      [param]: !this.state.cb[param],
    },
  });
}

这是因为JS使用了truthy values,所以undefined会被解释为false