Skip to content

Instantly share code, notes, and snippets.

@alanfoandrade
Created July 8, 2020 21:47
Show Gist options
  • Save alanfoandrade/0689ee2da66c5afc9453d8f46899f2fb to your computer and use it in GitHub Desktop.
Save alanfoandrade/0689ee2da66c5afc9453d8f46899f2fb to your computer and use it in GitHub Desktop.
Picker nativo do react-native estilizado e integrado ao unform
import React, {
useState,
useEffect,
useCallback,
useRef,
useImperativeHandle,
forwardRef,
} from 'react';
import { useField } from '@unform/core';
import PropTypes from 'prop-types';
import { Container, RNPicker, ErrorText } from './styles';
/**
* a função recebida setSelectedValue é opcional e é utilizada para manipular um estado externo
* no caso foi criada para setar um estado externo que foi utilizado em um useEffect para fazer uma
* chamada à api utilizando esse valor
*/
function NativePicker({ name, options, setSelectedValue = () => {} }, ref) {
const inputElementRef = useRef(null);
// eslint-disable-next-line
const [option, setOption] = useState('');
const { registerField, defaultValue = '', fieldName, error } = useField(name);
const inputValueRef = useRef({ value: defaultValue });
useImperativeHandle(ref, () => ({
focus() {
inputElementRef.current.focus();
},
}));
useEffect(() => {
registerField({
name: fieldName,
ref: inputValueRef.current,
path: 'value',
setValue(_, value) {
inputValueRef.current.value = value;
inputElementRef.current.setNativeProps({ text: value });
},
clearValue() {
inputValueRef.current.value = '';
inputElementRef.current.clear();
},
});
}, [fieldName, registerField]);
const handleSelect = useCallback(
(value) => {
setOption(value);
setSelectedValue(value);
inputValueRef.current.value = value;
},
[setSelectedValue]
);
return (
<Container>
<RNPicker
ref={inputElementRef}
mode="dropdown"
selectedValue={inputValueRef.current.value}
onValueChange={handleSelect}
>
<RNPicker.Item label="" value="" />
{options.map((opt) => (
<RNPicker.Item key={opt.id} label={opt.name} value={opt.name} />
))}
</RNPicker>
<ErrorText hasError={!!error} style={{ color: '#C53030' }}>
{error}
</ErrorText>
</Container>
);
}
export default forwardRef(NativePicker);
NativePicker.propTypes = {
name: PropTypes.string.isRequired,
options: PropTypes.arrayOf(PropTypes.shape()).isRequired,
setSelectedValue: PropTypes.func,
};
NativePicker.defaultProps = {
setSelectedValue: () => {},
};
import styled from 'styled-components/native';
import { Picker } from 'react-native';
import colors from '../../styles/colors';
export const Container = styled.View`
height: 45px;
border-bottom-width: 1px;
border-bottom-color: ${colors.secondaryVariant};
flex-direction: row;
`;
export const RNPicker = styled(Picker)`
height: 45px;
width: 100%;
`;
export const ErrorText = styled.Text`
display: ${(props) => (props.hasError ? 'flex' : 'none')};
position: absolute;
right: 0;
`;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment