Reputation: 182
Hey there I'm still learning with React Native and I have this custom picker component for iOS, and what I'm going to do is I want to clear the picker when I do onSubmit()
. What should I do to set the picker state to its default state when I do onSubmit()
from another component
PickerWrapper.js
class PickerWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
type_absen: this.props.items[0].description,
modal: false
}
}
render() {
let picker;
let iosPickerModal = (
<Modal isVisible={this.state.modal} hideModalContentWhileAnimating={true} backdropColor={color.white} backdropOpacity={0.9} animationIn="zoomInDown" animationOut="zoomOutUp" animationInTiming={200} animationOutTiming={200} onBackButtonPress={() => this.setState({ modal: false })} onBackdropPress={() => this.setState({ modal: false })} >
<View style={{ backgroundColor: color.white, width: 0.9 * windowWidth(), height: 0.3 * windowHeight(), justifyContent: 'center' }}>
<Picker
selectedValue={this.state.type_absen}
onValueChange={(itemValue, itemIndex) => {
this.setState({ type_absen: itemValue });
this.setState({ modal: false });
setTimeout(() => this.props.onSelect(itemValue), 1200);
}}
>
{this.props.items.map((item, key) => <Picker.Item label={item.description} value={item.id} key={item.id} />)}
</Picker>
</View>
</Modal>);
if (Platform.OS === 'ios') {
var idx = this.props.items.findIndex(item => item.id === this.state.type_absen);
return (
<View style={this.props.style}>
{iosPickerModal}
<TouchableOpacity onPress={() => this.setState({ modal: true })}>
<View style={{ flexDirection: 'row', height: this.props.height ? this.props.height : normalize(40), width: this.props.width ? this.props.width : 0.68 * windowWidth(), borderWidth: 1, borderColor: color.blue, alignItems: 'center', borderRadius: 5 }}>
<Text style={{ fontSize: fontSize.regular, marginRight: 30 }}> {idx !== -1 ? this.props.items[idx].description : this.state.type_absen}</Text>
<IconWrapper name='md-arrow-dropdown' type='ionicon' color={color.light_grey} size={20} onPress={() => this.setState({ modal: true })} style={{ position: 'absolute', right: 10 }} />
</View>
</TouchableOpacity>
</View >);
}
}
}
This is where I called my picker
App.js
class App extends Component {
constructor() {
super();
this.state = {
type_absen: ''
}
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit() {
this.props.actionsAuth.changeSchedule(this.props.token, this.state.type_absen, (message) => alert(message));
this.setState({ type_absen: ''});
}
render(){
let scheduleTypes = this.props.schedules;
return(
<PickerWrapper items={[{ "description": "Schedule Type", "id": "0" }, ...scheduleTypes]} onSelect={(item) => this.setState({ type_absen: item })} />
);
}
}
Upvotes: 1
Views: 342
Reputation: 2719
To update the child (PickerWrapper) from the parent, you have to create a new method in the child and call it from the parent.
For this, the parent should have the child reference
to have the ability to call some method from it
class App extends Component {
constructor() {
super();
this.state = {
type_absen: ''
}
this.pickerRef = undefined;
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit() {
this.props.actionsAuth.changeSchedule(this.props.token, this.state.type_absen, (message) => alert(message));
this.setState({ type_absen: ''});
this.pickerRef.reset();
}
render(){
let scheduleTypes = this.props.schedules;
return(
<PickerWrapper
ref={ref => ref && this.pickerRef = ref}
items={[{ "description": "Schedule Type", "id": "0" }, ...scheduleTypes]}
onSelect={(item) => this.setState({ type_absen: item })} />
);
}
}
And then, create the reset method in the child :
class PickerWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
type_absen: this.props.items[0].description,
modal: false
}
}
reset = () => {
this.setState({type_absen: this.props.items[0].description, modal: false})
}
render() {
let picker;
let iosPickerModal = (
<Modal isVisible={this.state.modal} hideModalContentWhileAnimating={true} backdropColor={color.white} backdropOpacity={0.9} animationIn="zoomInDown" animationOut="zoomOutUp" animationInTiming={200} animationOutTiming={200} onBackButtonPress={() => this.setState({ modal: false })} onBackdropPress={() => this.setState({ modal: false })} >
<View style={{ backgroundColor: color.white, width: 0.9 * windowWidth(), height: 0.3 * windowHeight(), justifyContent: 'center' }}>
<Picker
selectedValue={this.state.type_absen}
onValueChange={(itemValue, itemIndex) => {
this.setState({ type_absen: itemValue });
this.setState({ modal: false });
setTimeout(() => this.props.onSelect(itemValue), 1200);
}}
>
{this.props.items.map((item, key) => <Picker.Item label={item.description} value={item.id} key={item.id} />)}
</Picker>
</View>
</Modal>);
if (Platform.OS === 'ios') {
var idx = this.props.items.findIndex(item => item.id === this.state.type_absen);
return (
<View style={this.props.style}>
{iosPickerModal}
<TouchableOpacity onPress={() => this.setState({ modal: true })}>
<View style={{ flexDirection: 'row', height: this.props.height ? this.props.height : normalize(40), width: this.props.width ? this.props.width : 0.68 * windowWidth(), borderWidth: 1, borderColor: color.blue, alignItems: 'center', borderRadius: 5 }}>
<Text style={{ fontSize: fontSize.regular, marginRight: 30 }}> {idx !== -1 ? this.props.items[idx].description : this.state.type_absen}</Text>
<IconWrapper name='md-arrow-dropdown' type='ionicon' color={color.light_grey} size={20} onPress={() => this.setState({ modal: true })} style={{ position: 'absolute', right: 10 }} />
</View>
</TouchableOpacity>
</View >);
}
}
}
Additionnaly, your component is re-render each time a setState is set. You can avoid double re-render by switching
this.setState({type_absen: itemValue});
this.setState({modal: false});
to this
this.setState({type_absen: itemValue, modal: false});
Upvotes: 2