无法更新父组件的状态。无法重置表单

时间:2021-04-14 08:07:24

标签: react-native

function DateTimePick 是一个子函数,用于在父组件 Reservation 中呈现选取的日期和选取的时间。目前代码有两个问题: 1. Reservation 中的表单提交数据后没有重置。 2. 子DateTimePick 无法更新父Reservation 中“日期”和“时间”的状态。请看一看,让我知道如何解决这些问题。谢谢。

子函数DateTimePick如下:

import React, {useState} from 'react';
import {View, Button, Platform, Text, TextInput, StyleSheet} from 'react-native';
import DateTimePicker from '@react-native-community/datetimepicker';
import { Icon } from 'react-native-elements';
import Moment from "moment";

export const DateTimePick = () => {  
  
  const [date, setDate] = useState(new Date());
  const [mode, setMode] = useState('date');
  const [show, setShow] = useState(false);
  
  const onChange = (event, selectedDate) => {
      const currentDate = selectedDate || date;
      setShow(Platform.OS === 'ios');
      setDate(currentDate);
  };
  
  const showMode = (currentMode) => {
      setShow(true);
      setMode(currentMode);
  };
  
  const showDatepicker = () => {
      showMode('date');
  };
  
  const showTimepicker = () => {
      showMode('time');
  };
    
      return (
      <View>                
          <View style={styles.formRow}>
              <Text style={styles.formLabel}> Date</Text>
              <Text onPress={showDatepicker} style={styles.formItem} value_date={date.toDateString()} onChange = {(value_date) => this.props.setState({date: value_date})}><Icon type='font-awesome-5' name='calendar' color='#512DA8' />{' ' + Moment(date).format('DD-MMM-YYYY') }</Text>
          </View>
          <View style={styles.formRow}>
              <Text style={styles.formLabel}> Time</Text>
              <Text onPress={showTimepicker} style={styles.formItem} value_time={date.toTimeString()} onChange = {(value_time) => this.props.setState({time: value_time})}><Icon type='font-awesome-5' name='clock' color='#512DA8' /> {' ' + Moment(date).format('h:mm A') }</Text>
          </View>
          {show && (
          <DateTimePicker
              testID="dateTimePicker"
              value={date}
              mode={mode}
              is24Hour={true}
              display="default"
              onChange={onChange}
          />
          )}        
      </View>
      );
  };

//export default DateTimePick;

const styles = StyleSheet.create({
  formRow: {
      alignItems: 'center',
      justifyContent: 'center',
      flex: 1,
      flexDirection: 'row',
      margin: 20
  },
  formLabel: {
      fontSize: 18,
      flex: 1
  },
  formItem: {
      flex: 1        
  },
  modal: {
      justifyContent: 'center',
      margin: 20
  },
  modalTitle: {
      fontSize: 24,
      fontWeight: 'bold',
      backgroundColor: '#512DA8',
      textAlign: 'center',
      color: 'white',
      marginBottom: 20
  },
  modalText: {
      fontSize: 18,
      margin: 10
  },
})

产生预订表格和预订输入确认模式的父预订

import React, {Component} from 'react';
import { Text, View, ScrollView, StyleSheet, Switch, Button, TextInput, Modal} from 'react-native';
import {DateTimePick} from './DateTimePickComponent';

class Reservation extends Component {
    constructor(props) {
        super(props);
        this.state = {
            guests: 1,
            smoking: false,
            notes:'',
            date: new Date().toDateString(),
            time: new Date().toTimeString(),
            showModal: false          
        }
    }

    toggleModal() {
        this.setState({showModal: !this.state.showModal})
    }

    handleReservation() {
        console.log(JSON.stringify(this.state));  //log current state
        //this.setState({                           // reset the form  
        //})
        this.toggleModal();
    }

    resetForm() {
        this.setState({
            guests: 1,
            smoking: false,
            notes:'',
            date: new Date().toDateString(),
            time: new Date().toTimeString(),
            showModal: false 
        });
    }

    
    render() {
            //, transform: [{ scaleX: 3 }, { scaleY: 1.5 }]   => for switch
        return(
            <ScrollView>
                <View style={styles.formRow}>
                    <Text style={styles.formLabel}> Guests </Text>
                    <TextInput style={styles.formItem} keyboardType="numeric" placeholder="Number" 
                        value_guests={this.state.guests}
                        onChangeText = {(value_guests) => this.setState({guests: value_guests})} >                                                   
                    </TextInput>
                </View>

                <View style={styles.formRow}>
                    <Text style={styles.formLabel}> Notes </Text>
                    <TextInput style={styles.formItem} keyboardType="default" placeholder="Allergy,..etc"  
                      value_notes={this.state.notes}
                      onChangeText = {(value_notes) => this.setState({notes: value_notes})} >                             
                    </TextInput>
                </View>                
                <View style={styles.formRow}>                     
                    <Text style={styles.formLabel}> Non-Smoking </Text>                   
                    <Switch style={{ flex: 1, backgroundColor: "orange", paddingLeft:0, marginLeft:0 }} trackColor={{true: 'red', false: 'grey'}}
                    value={this.state.smoking} 
                    onValueChange = {(value) => this.setState({smoking: value})} />
                    <Text style={styles.formLabel}> Smoking </Text>                    
                </View>
                                          
                <DateTimePick />

                <View style={styles.formRow}>
                    <Button
                        onPress={() => this.handleReservation()}
                        title="Reserve"
                        color="#512DA8"
                        accessibilityLabel="Learn more about this purple button"
                        />
                </View>

                <Modal animationType={'slide'} transparent={false} visible={this.state.showModal}
                onDismiss={() => {this.toggleModal()}}
                onRequestClose={() => {this.toggleModal()}}>
                    <View style={styles.modal}>
                        <Text style={styles.modalTitle}>Your Reservation</Text>
                        <Text style={styles.modalText}>Number of Guests: {this.state.guests}</Text>
                        <Text style={styles.modalText}>Notes: {this.state.notes}</Text>
                        <Text style = {styles.modalText}>Smoking?: {this.state.smoking ? 'Yes' : 'No'}</Text>
                        <Text style = {styles.modalText}>Date and Time: {this.state.date} {this.state.time}</Text>
                        <Button 
                            onPress = {() =>{this.toggleModal(); this.resetForm();}}
                            color="#512DA8"
                            title="Close" 
                            />
                    </View>

                </Modal>
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    formRow: {
        alignItems: 'center',
        justifyContent: 'center',
        flex: 1,
        flexDirection: 'row',
        margin: 20
    },
    formLabel: {
        fontSize: 18,
        flex: 1
    },
    formItem: {
        flex: 1        
    },
    modal: {
        justifyContent: 'center',
        margin: 20
    },
    modalTitle: {
        fontSize: 24,
        fontWeight: 'bold',
        backgroundColor: '#512DA8',
        textAlign: 'center',
        color: 'white',
        marginBottom: 20
    },
    modalText: {
        fontSize: 18,
        margin: 10
    },
})

export default Reservation;

2 个答案:

答案 0 :(得分:1)

您可以通过将 state consts date、show、mode 转移到父 Reservation 来修复它

然后将状态更改函数传递给如下道具中的 DateTimePick 组件

<DateTimePick onDateChange={(date) => this.setState({date: date}) } />

在 DateTimePick 组件中:

 const onChange = (event, selectedDate) => {
      const currentDate = selectedDate || date;
      setShow(Platform.OS === 'ios');
      props.onDateChange(currentDate);
  };

也不要忘记在组件中传递 props 就像

export const DateTimePick = (props) => { 

答案 1 :(得分:0)

解决了。使用子数据更新父状态需要传递一个处理程序来设置父状态为子,参考How to update parent's state in React?

class Parent extends React.Component {
  constructor(props) {
    super(props)

    this.handler = this.handler.bind(this)
  }

  handler() {
    this.setState({
      someVar: 'some value'
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <Button onClick = {this.props.handler}/ >
  }
}

在实现中,一个handler被插入到父类Reservation中,如下

...
class Reservation extends Component {
    constructor(props) {
...
this.handler = this.handler.bind(this) 
    }

    handler(selectedDate) {
        this.setState({
            date: Moment(selectedDate).format('DD-MMM-YYYY'),
            time: Moment(selectedDate).format('h:mm A'), 
        })
      }
...

在子 DateTimePick 中,将处理程序嵌入 onChange 以将子更新从 onChange 传递到父 Reservation 中的状态更新,如下所示

...

export const DateTimePick = (props) => {
    const handler = props.handler;
    ...

    const onChange = (event, selectedDate) => {
        ...
        handler(currentDate);
    };
...
...