Automatically show keyboard on first render of react-native-confirmation-code-field - reactjs

I am using the react-native-confirmation-code-field package. I want the keyboard to be showing as soon as the screen renders and the first cell in focus. Any ideas how to do this?
Edit: Including my code below:
export default function ConfirmationCode({ route, navigation }) {
const [value, setValue] = useState("")
const ref = useBlurOnFulfill({ value, cellCount: CELL_COUNT })
const [props, getCellOnLayoutHandler] = useClearByFocusCell({value, setValue})
return (
<CodeField
ref={ref}
{...props}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFieldRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={({ index, symbol, isFocused }) => (
<Text
key={index}
style={[styles.cell, isFocused && styles.focusCell]}>
{symbol || (isFocused ? <Cursor /> : null)}
</Text>
)
}
/>
)
}

Change Text component to TextInput. But make sure it is disabled.
Set a ref(you would need the first one).
And on useEffect, call the focus method on that ref.
Roughly, it should look something like this:
export default function ConfirmationCode({ route, navigation }) {
const [value, setValue] = useState("")
const ref = useBlurOnFulfill({ value, cellCount: CELL_COUNT })
const [props, getCellOnLayoutHandler] = useClearByFocusCell({value, setValue})
const textInputRef = useRef(null);
useEffect(() => {
textInputRef.current?.focus()
}, []);
return (
<CodeField
ref={ref}
{...props}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFieldRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={({ index, symbol, isFocused }) => (
<TextInput
key={index}
ref={index === 0 && textInputRef)
style={[styles.cell, isFocused && styles.focusCell]}>
{symbol || (isFocused ? <Cursor /> : null)}
</TextInput>
)
}
/>
)
}

So it turns out that CodeField does have an autoFocus property, my bad. The solution is simply to add autoFocus={true} as a prop to the CodeField component:
<CodeField
ref={ref}
{...props}
autoFocus={true}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFieldRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={({ index, symbol, isFocused }) => (
<TextInput
key={index}
ref={index === 0 && textInputRef)
style={[styles.cell, isFocused && styles.focusCell]}>
{symbol || (isFocused ? <Cursor /> : null)}
</TextInput>
)
}
/>

Related

State of Dynamically Generated Radio Buttons

I'm trying to pass a class only to the checked radio button in my component, but with my existing code all the radio buttons receive the class. Any advice?
export default function RadioGroup({options}){
const [isChecked, setIsChecked] = useState(false);
return(
<>
{options.map(option => {
return (
<Radio
radioID={option.id}
radioName={name}
radioLabel={option.label}
radioClass={` ${isChecked ? "bg-blue" : ""}`}
onChange={() => setIsChecked((prev) => !prev)}
/>
)
})}
</>
);
}
Instead of passing Boolean in setIsChecked, you have to pass the id then you can add the bg-blue class on id base, as you can see the below code.
export default function RadioGroup({options}){
const [isChecked, setIsChecked] = useState(null);
return(
<>
{options.map(option => {
return (
<Radio
radioID={option.id}
radioName={name}
radioLabel={option.label}
radioClass={` ${(isChecked === option.id) ? "bg-blue" : ""}`}
onChange={() => setIsChecked(option.id)}
/>
)
})}
</>
);
}

How do I reset my datepicker component using Formik ResetForm() after handleSubmit?

I created a datepicker component from '#react-native-community/datetimepicker' that shows a placeholder title that changes into a selected date after the datetimepicker was chosen. But it would not reset back to its placeholder after handleSubmit while other components reset to their placeholder titles. I have tried modifying the Formik values but didn't work. Now I am thinking I made a mistake somewhere in creating the datepicker component such that it does not deem the title as its default state. Excerpt below:
function AppFormDate({ name, placeholder }) {
const {errors, setFieldValue, touched, values} = useFormikContext();
return (
<React.Fragment>
<AppDatePicker
onSelectItem={(selectedDate) => setFieldValue(name, selectedDate)}
placeholder={placeholder}
value={values[name]}>
</AppDatePicker>
<AppErrorMessage
error={errors[name]}
visible={touched[name]}>
</AppErrorMessage>
</React.Fragment>
);
}
function AppDatePicker({ icon, onSelectItem, placeholder }) {
const [date, setDate] = useState(new Date());
const [mode, setMode] = useState();
const [show, setShow] = useState(false);
const [title, setTitle] = useState(placeholder);
const onSelect = (selectedDate) => {
const currentDate = selectedDate || date;
setShow(Platform.OS === 'ios');
setDate(currentDate);
let tempDate = new Date(currentDate);
let fDate = tempDate.getFullYear() + '-' + (tempDate.getMonth() + 1) + '-' + tempDate.getDate();
// console.log(selectedDate)
onSelectItem(fDate);
setTitle(fDate.toString())
}
const showMode = (currentMode) => {
setShow(true);
setMode(currentMode);
}
return (
<View>
<TouchableWithoutFeedback onPress={() => showMode('date')}>
<View style={styles.container}>
{icon &&
<MaterialCommunityIcons
color={colors.black}
name={icon}
size={20}
style={styles.icon}>
</MaterialCommunityIcons>
}
{
onSelect ? (
<AppText style={styles.text}>{title}</AppText>
) : (
<AppText style={styles.placeholder}>{placeholder}</AppText>
)
}
<MaterialCommunityIcons
color={colors.black}
name="chevron-down"
size={20}>
</MaterialCommunityIcons>
</View>
</TouchableWithoutFeedback>
{show &&
<DateTimePicker
display='default'
mode={mode}
onChange={(_, date) => onSelect(date)}
value={date}>
</DateTimePicker>
}
</View>
);
}

Customise Select Menu in React

UPDATED!
I'm creating a wrapper for dropdown menu and use it in several components so I need to make such a Menu generic. The problem is I do not understand how to pass external variables into such a component.
My component:
const SelectOptionsPaginated = ({
alignment, minWidth, width,
rowData,
column
}) => {
..........
const Menu = (props) => {
const {options} = props;
const dropdownContainer = useRef(null);
const [maxMenuHeight, setMaxMenuHeight] = useState(300)
const [dropDownStyle, setDropDownStyle] = useState({
position: "absolute",
minWidth: `${minWidth ? minWidth + "px" : "100%"}`,
maxWidth: `${width}px`,
maxHeight: `${maxMenuHeight}px`,
top: `32px`
})
const getDropdownPosition = (elem) => {
setDropDownStyle({
...dropDownStyle,
...getDropdownAlignment(elem, setMaxMenuHeight, gridId, options, true)
})
};
useEffect(() => {
const optionsList = dropdownContainer.current
if (!optionsList) return
getDropdownPosition(optionsList)
}, [options])
return (
<div
className="dropdown-container"
ref={dropdownContainer}
style={dropDownStyle}
>
<components.Menu {...props} >
{props.children}
</components.Menu>
</div>
)
}
............
return <AsyncPaginate
additional={defaultAdditional}
isMulti={isMulti}
value={value}
loadOptions={loadOptions}
onChange={handleChange}
escapeClearsValue
isClearable
styles={getStylesForSelectorEditor(width, minWidth, newAlignment)}
components={{Menu}}
/>
such variables as minWidth, width should be passed externally to Menu.
I tried something like:
...............
return <AsyncPaginate
additional={defaultAdditional}
isMulti={isMulti}
value={value}
loadOptions={loadOptions}
onChange={handleChange}
escapeClearsValue
isClearable
styles={getStylesForSelectorEditor(width, minWidth, newAlignment)}
// pseudocode
components={{<Menu width={100}/>}} or
components={{Menu(100)}}
/>
but it doesn't work.
I tried to google but didn't find clear information. I'm new in react so will appreciate any help.
Did you meant something like that?
const AsyncPaginate= (props) => {
const {components} = props;
return (
<>
{components}
</>
)
}
const Menu = () => {
return (
<>
something...
</>
)
}
const App = () => {
return (
<>
<AsyncPaginate components={<Menu />}></AsyncPaginate>
</>
)
}

reactjs - Popup : Showing a popup withouth clicking a button

Im tying to show up a pop up whit the following code :
const [showPopup, setShowPopup] = useState(false);
Im handling the show/setpopup by this way :
<Popup open={showPopup} onClose={() => setShowPopup(false)} modal>
<span> Popup content </span>
</Popup>
{meta.error === 'codigo 2 fatores incorreto' ? (
setShowPopup(true)
) : (
<Popup style={{ visibility: "hidden" }}>.</Popup>
)}
When it drops in the case (meta.error === 'codigo 2 fatores incorreto') he drops in a loop with the following eror : (Too many re-renders. React limits the number of renders to prevent an infinite loop. ) , someone knows how to solute it ?
I used this doc https://react-popup.elazizi.com/component-api/
whole component [WORKING] :
import React, { useState, useEffect } from 'react';
import { ErrorMessage, useField } from "formik";
import { StyledTextInput, StyledLabel, StyledIcon, ErrorMsg } from "./Styles";
// Eye for password
import { FiEyeOff, FiEye } from "react-icons/fi";
//pop up style.css
import '../assets/css/popup.css'
// Import popup lib
import Popup from "reactjs-popup";
import 'reactjs-popup/dist/index.css';
function MyComponent() {
const [state, setState] = useState();
setState(true);
return (
<Popup model
trigger={open => <MyComponent open={open} />}
position="right center"
closeOnDocumentClick
>
<span> Popup content </span> </Popup>
);
}
export const TextInput = ({ icon, ...props }) => {
const [field, meta] = useField(props);
const [showpass, setShowpass] = useState(false);
const [showPopup, setShowPopup] = useState(false);
useEffect(() => {
if(meta.error === 'codigo 2 fatores incorreto'){
setShowPopup(true);
}
}, [meta.error])
return (
<div style={{ position: "relative" }}>
<StyledLabel htmlFor={props.name}>{props.label}</StyledLabel>
{props.type !== "password" && (
<StyledTextInput
invalid={meta.touched && meta.error}
{...field}
{...props}
/>
)}
{props.type === "password" && (
<StyledTextInput
invalid={meta.touched && meta.error}
{...field}
{...props}
type={showpass ? "text" : "password"}
/>
)}
<StyledIcon>{icon}</StyledIcon>
{props.type === "password" && (
<StyledIcon onClick={() => setShowpass(!showpass)} right>
{showpass && <FiEye />}
{!showpass && <FiEyeOff />}
</StyledIcon>
)}
{meta.touched && meta.error ? (
<ErrorMsg>{meta.error}</ErrorMsg>
) : (
<ErrorMsg style={{ visibility: "hidden" }}>.</ErrorMsg>
)}
<Popup open={showPopup} onClose={() => setShowPopup(false)} modal>
{close => (
<div className="modal">
<button className="close" onClick={close}>
×
</button>
</div>
)}
</Popup>
{meta.error === "codigo 2 fatores incorreto" ? (
!showPopup ? ( setShowPopup(true)) : ("") // <-- Only set state if not true
) : <Popup>.</Popup>}
</div>
);
};
We should never ever use a setState inside the components render method. For class components, that is inside the render(), for function components, that is anywhere inside return() or in the component body, like here:
function MyComponent() {
const [state, setState] = useState();
setState(true);
return (...);
}
This will always cause an infinite loop.
setState() triggers re-render.
Re-render runs the component code again and triggers setState(). Go back to 1.
React provides tools to handle your case, such as useEffect.
Instead of
{meta.error === "codigo 2 fatores incorreto" ? (
setShowPopup(true)
) : (
<Popup style={{ visibility: "hidden" }}></Popup>
)}
You should have
export const TextInput = ({ icon, ...props }) => {
...
useEffect(() => {
if(meta.error){
setShowPopup(true);
}
}, [meta.error])
return (
...
<Popup style={{visibility: "hidden"}}>.</Popup>
);
If I'm reading this right, it seems whenever meta.error matches your string, it'll constantly call setShowPopup(true) because the state updated - and calling that function causes the re-render, during which I assume meta.error is still 'codigo 2 fatores incorreto'.
I believe you could do something like the following to stop the re-rendering.
{meta.error === "codigo 2 fatores incorreto" ? (
!showPopup ? setShowPopup(true) : "" // <-- Only set state if not true
) : (
<Popup style={{visibility: "hidden"}}>.</Popup>
)}
I may be wrong though, and I may be misunderstanding the snippet.

React native render component based on TextInput onfocus

I want to display something in my react component when user clicks into a text input (something similar to Instagram's search, where if you click on their input field, a search component suggestion shows up.
const SearchScreen = props => {
const renderSearch = () => {
return (
<>
// need to display the search suggestion
</>
)
}
return (
<>
<TextInput
placeholder="Search"
onChangeText={text => handleChange(text)}
value={searchText}
onFocus={() => renderSearch()} // based on focus, then render component
/>
<View>
// how do I render here?
// this will render on load, but need to render onFocus
{renderSearch}
</View>
</>
);
};
You can apply a similar pattern than stackoverflow.com/a/34091564/1839692.
For instance you can try something like :
const SearchScreen = props => {
const [searchFocus, setSearchFocus] = useState(false)
const renderSearch = () => {
return (
<>
// need to display the search suggestion
</>
)
}
return (
<>
<TextInput
placeholder="Search"
onChangeText={text => handleChange(text)}
value={searchText}
onFocus={() => setSearchFocus(true)}
onBlur={() => setSearchFocus(false)}
/>
{ searchFocus
? <View>
{renderSearch}
</View>
: <View>
// Add here the code to display when not searching
</View>
}
</>
);
};

Resources