Reputation: 2049
I'm in the process of building my first React Native library, but it's coming along with some issues of course. 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.
App.js (Will Eventually be a NPM package, but using App for test)
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. 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. My question is further explained in the ListPicker.js description.
// 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
Here is the ListPicker component and the value when selected from the Picker is value
and is set with setValue
.
MY QUESTION: *How can I pass the value
in my React Hook to my onValueChange
in the parent component? Do I do that in the selectValue
method?
// 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,
},
});
Upvotes: 2
Views: 1533
Reputation: 5266
onValueChange
is a function which you need to call when you need to pass new value to parent component, according to your code:
// DO SOMETHING HERE??
just props.onValueChange(value)
Upvotes: 1
Reputation: 3117
Yes. Just call the props.onValueChange
with the changed value inside selectValue
method.
// 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
Upvotes: 2