React Hook:将Hook状态传递回父组件

时间:2020-01-08 09:10:40

标签: reactjs react-native state react-hooks

我正在构建我的第一个React Native库,但是当然还有一些问题。这是React Native的一个小型选择器组件库(日期,时间,日期时间,列表,状态),但是我需要一些有关下一步操作的指南。

App.js(最终将是NPM程序包,但使用App进行测试)

我想使用onValueChange,以便用户从NPM包导入组件时可以使用setState将状态设置为屏幕状态。截至目前,它只是将值记录到控制台(但是该值未正确传递,因此不起作用)。这就是为什么我将onValueChange作为ListPicker组件的原因。 ListPicker.js说明中进一步解释了我的问题。

// Imports: Dependencies
import React, { useState, useEffect } from 'react';

// Imports: Components
import { ListPicker } from './src/ListPicker';

// React Native App
export default App = () => {

  // Test Data
  const items = [
    { label: '1', value: '1' },
    { label: '2', value: '2' },
    { label: '3', value: '3' },
    { label: '4', value: '4' },
    { label: '5', value: '5' },
    { label: '6', value: '6' },
    { label: '7', value: '7' },
    { label: '8', value: '8' },
    { label: '9', value: '9' },
    { label: '10', value: '10' }
  ];

  return (    
    <ListPicker listName="List Test" items={items} onValueChange={(value) => console.log(`Value Updated: ${value}`)}/>
  );
};

ListPicker.js

这里是ListPicker组件,并且从Picker中选择时的值为value,并用setValue进行设置。

我的问题:*如何将React Hook中的value传递给父组件中的onValueChange?我可以使用selectValue方法吗?

// Imports: Dependencies
import React, { useState } from 'react';
import { Button, DatePickerAndroid, DatePickerIOS, Dimensions, Platform, Picker, SafeAreaView, StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import Modal from 'react-native-modal';
import Icon from 'react-native-vector-icons/Ionicons';
Icon.loadFont();

// Screen Dimensions
const { height, width } = Dimensions.get('window');

// Component: List Picker
export const ListPicker = (props) => {
  // React Hooks: State
  const [ modalVisible, toggle ] = useState(false);
  const [ value, setValue ] = useState();

  // React Hooks: Lifecycle Methods



  // Toggle Modal
  toggleModal = () => {
    try {
      // React Hook: Toggle Modal
      toggle((modalVisible) => !modalVisible);
    }
    catch (error) {
      console.log(error);
    }
  };

  // Select Value
  selectValue = (value) => {
    try {
      // React Hook: Set Value
      setValue(value);

      // React Props: onValueChange
      // DO SOMETHING HERE??
    }
    catch (error) {
      console.log(error);
    }
  };

  // Render Picker Type
  renderPickerType = () => {
    try {
      // Check Platform (iOS)
      if (Platform.OS === 'ios') {

        return (
          <Picker
            selectedValue={value}
            onValueChange={this.selectValue}>
            {props.items.map((item) => {
              return (
                <Picker.Item
                  label={item.label}
                  value={item.value}
                  key={item.key || item.label}
                  color={item.color}
                />
              );
            })}
          </Picker>
        )
      }

      // Check Platform (Android)
      if (Platform.OS === 'android') {

      }
    }
    catch (error) {
      console.log(error);
    }
  };

  return (
    <View style={styles.container}>
      <View style={styles.inputTitleContainer}>
      <Text style={styles.inputTitle}>{props.listName}</Text>
      </View>

      <TouchableOpacity onPress={this.toggleModal} style={styles.fieldTextContainer}>
        <Text style={styles.fieldText}>{value !== undefined ? value : 'Select'}</Text>

        <Icon name="ios-arrow-forward" size={22} style={styles.arrowForward}/>
      </TouchableOpacity>

      <Modal
        isVisible={modalVisible}
        style={styles.modal}
      >
        <View style={styles.modalContainer}>
          <View style={styles.pickerHeaderContainer}>
            <TouchableOpacity onPress={this.toggleModal} >
              <Text style={styles.doneText}>Done</Text>
            </TouchableOpacity>
          </View>

          <View style={styles.pickerContainer}>
            {this.renderPickerType()}
          </View>
        </View>
      </Modal>
    </View>
  );
}

// Styles
const styles = StyleSheet.create({
  container: {
    display: 'flex',
    width: width - 32,
    marginLeft: 16,
    marginRight: 16,
    justifyContent: 'center',
  },
  modal: {
    margin: 0,
  },
  modalContainer: {
    height: '100%',
    alignItems: 'center',
    justifyContent: 'flex-end',
  },
  pickerHeaderContainer: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignItems: 'center',
    height: 40,
    width: width,
    backgroundColor: '#FAFAF8',
    borderColor: '#7D7D7D',
    borderBottomWidth: StyleSheet.hairlineWidth,
  },
  pickerContainer: {
    height: 220,
    width: width,
    // backgroundColor: '#CFD3D9',
    backgroundColor: 'white',
  },
  doneText: {
    fontFamily: 'System',
    color: '#007AFF',
    fontWeight: '600',
    fontSize: 17,
    marginRight: 16,
  },
  stateContainer: {
    alignItems: 'center',
    width: 75,
    borderColor: '#7D7D7D',
    borderBottomWidth: StyleSheet.hairlineWidth,
  },
  inputTitleContainer: {
    width: 75,
    marginBottom: 4,
  },
  inputTitle: {
    color: '#7D7D7D',
    borderColor: '#7D7D7D',
    fontSize: 10,
    fontWeight: '600',
    textTransform: 'uppercase',
  },
  fieldTextContainer: {
    height: 40,
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 4,
    borderColor: '#7D7D7D',
    borderBottomWidth: StyleSheet.hairlineWidth,    
  },
  fieldText: {
    fontFamily: 'System',
    fontSize: 17,
    fontWeight: '400',
    color: '#000000',
    alignSelf: 'center',
  },
  arrowForward: {
    color: 'black',
    opacity: .3,
    marginRight: 7,
  },
});

2 个答案:

答案 0 :(得分:2)

是的。只需在props.onValueChange方法中使用更改后的值调用selectValue

  // Select Value
  selectValue = (value) => {
      // React Hook: Set Value
      setValue(value);

      // React Props: onValueChange
      props.onValueChange(value)
  };

顺便说一句,您不需要在所有地方都使用try catch:D

答案 1 :(得分:1)

onValueChange是一个函数,需要根据代码将新值传递给父组件时调用:

//这里有事吗?

props.onValueChange(value)

相关问题