Created
July 8, 2020 21:47
-
-
Save alanfoandrade/0689ee2da66c5afc9453d8f46899f2fb to your computer and use it in GitHub Desktop.
Picker nativo do react-native estilizado e integrado ao unform
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: () => {}, | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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