简体   繁体   English

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

[英]React Hooks: Passing Hook State back to Parent Component

I'm in the process of building my first React Native library, but it's coming along with some issues of course.我正在构建我的第一个 React Native 库,但它当然会带来一些问题。 It's a small picker component library (date, time, datetime, list, states) for React Native, but I'm need some guidance as to how to do the next step.这是一个用于 React Native 的小型选择器组件库(日期、时间、日期时间、列表、状态),但我需要一些关于如何进行下一步的指导。

App.js (Will Eventually be a NPM package, but using App for test) App.js(最终会是一个 NPM 包,但使用 App 进行测试)

I want to use the onValueChange so a user can use setState to set the state to their screen when importing the component from the NPM package.我想使用onValueChange以便用户可以在从 NPM 包导入组件时使用setState将状态设置为他们的屏幕。 As of right now, it's just logging the value to the console (but the value isn't being passed correctly, so that doesn't work).截至目前,它只是将值记录到控制台(但该值未正确传递,因此不起作用)。 That's why I have onValueChange as a ListPicker component prop.这就是为什么我将onValueChange作为 ListPicker 组件道具。 My question is further explained in the ListPicker.js description.我的问题在 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列表选择器.js

Here is the ListPicker component and the value when selected from the Picker is value and is set with setValue .这是 ListPicker 组件,从 Picker 中选择时的值是value并使用setValue设置。

MY QUESTION: *How can I pass the value in my React Hook to my onValueChange in the parent component?我的问题: *如何将 React Hook 中的value传递给父组件中的onValueChange Do I do that in the selectValue method?我在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,
  },
});

Yes.是的。 Just call the props.onValueChange with the changed value inside selectValue method.只需在selectValue方法中使用更改后的值调用props.onValueChange selectValue

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

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

BTW, You don't need to use try catch everywhere :D顺便说一句,你不需要在任何地方都使用try catch :D

onValueChange is a function which you need to call when you need to pass new value to parent component, according to your code: onValueChange是一个函数,当您需要根据您的代码将新值传递给父组件时,您需要调用该函数:

// DO SOMETHING HERE?? // 在这里做点什么??

just props.onValueChange(value)只是props.onValueChange(value)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM