Toggle text on pressing the button in react native - toggle

I am new to react native and I want to toggle text on pressing the button, but the problem is that when I press button the text changed but when I press it again nothing happen. Here is my code:
enter image description here

When you use react hooks, you configure the component to do things after it renders. If you declare a variable outside of a useState hook, it will be reset on every render. This is what happens to your isTrue variable. Read more about the rules of hooks here.
You also don't need to evaluate isTrue == true, you can just call isTrue, it will have the same effect.
export default function App() {
var startingText = "First text"
const [isTrue, setIsTrue] = useState(true)
const [outputText, setOutputText] = useState(startingText)
function textChange() {
setIsTrue(!isTrue)
return isTrue ? startingText : setOutputText("Text Changed")
}
return(
<View>
<Text>{outputText}</Text>
<Button title="Change Text" onPress={textChange}/>
</View>
)
}
You can simplify the code even further by removing the boolean variable and moving the logic of selecting which text value to set in the textChange function directly using a ternary operator.
export default function App() {
var startingText = ""
const [outputText, setOutputText] = useState(startingText)
function textChange() {
setOutputText(outputText === startingText ? "Text Changed" : startingText)
}
return(
<View>
<Text>{outputText}</Text>
<Button title="Change Text" onPress={textChange}/>
</View>
)
}

Try to change the function on:
const [tooggle, setToggle] = useState(false);
function textChange() {
setToggle(!tooggle);
return isTrue === tooggle
? setOutputText('first')
: setOutputText('second');
}
Example of toggle:
import React, { useState } from 'react';
import { Button, View, Text } from 'react-native';
const ToggleFunction = () => {
const [outPutText, setOutputText] = useState('first');
const [tooggle, setToggle] = useState(false);
function textChange() {
setToggle(!tooggle);
return tooggle ? setOutputText('first') : setOutputText('second');
}
return (
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}
>
<Text>{outPutText}</Text>
<Button title="button" onPress={textChange} />
</View>
);
};
export { ToggleFunction };

Related

changing the variant of the Button onClick MUI

I want to change the variant of the Button component whenever it gets clicked, from 'outlined' to 'contained':
<Button variant='outlined'>Click me to change my variant to contained</Button>
Is that possible in MUI? using React refs? or how can I achieve this?
you can achieve it like this:
import React, { useState } from 'react';
function App() {
const [currentButtonVariant, setCurrentButtonVariant] = useState('outlined');
const handleButtonVariantChange = () => {
if (currentButtonVariant === 'outlined') {
setCurrentButtonVariant('contained');
}
else {
setCurrentButtonVariant('outlined');
}
}
return (
<div className="App">
<Button variant={currentButtonVariant} onClick={handleButtonVariantChange}>Click me to change my variant to contained</Button>
</div>
);
}

How to submit a form using a function? React Native

I want to submit a form when I stop type, I'm using react hook form and call the handleSubmit in a function and it doesn't work, please help me, this is my code, I'm doing a map of this code, I've tried with ref but it doesn't work. This is my component.
import React, {useRef} from 'react';
import {View, Text, TextInput, TouchableOpacity} from 'react-native';
import tailwind from 'tailwind-rn';
import {useDebounce} from 'use-debounce';
import {useForm, Controller} from 'react-hook-form';
import {MAIN_COLOR, GRAY} from '../../constants/theme';
function RegisterFormHook({data, onSubmit, control, errors}) {
const [underlineColor, setUnderlineColor] = React.useState(GRAY);
const [field, setField] = React.useState('');
const [value] = useDebounce(field, 1000);
const inputElement = useRef();
const {handleSubmit} = useForm();
React.useEffect(() => {
if (value.length !== 0) {
handleSubmit(onSubmit({[data.name]: value}));
}
console.log(errors);
}, [value]);
const onFocus = () => {
setUnderlineColor(MAIN_COLOR);
};
const onBlur = () => {
setUnderlineColor(GRAY);
};
return (
<View style={tailwind('px-8')}>
<Controller
control={control}
name={data.name}
rules={data.rules}
render={({field: {onChange, value}}) => (
<TextInput
placeholder={data.placeholder}
ref={inputElement}
style={[
tailwind('text-black p-0 text-xl pb-1 flex-row'),
{
borderBottomWidth: 1,
borderBottomColor: underlineColor,
},
]}
onChangeText={value => {
onChange(value);
setField(value);
}}
onBlur={onBlur}
value={value}
onFocus={() => onFocus()}
/>
)}
/>
<Text>{errors[data.name]?.message}</Text>
</View>
);
}
export default RegisterFormHook;
I want to submit in the useEffect but it just works when I press a button.
Here is a sample how you could implement scheduled action after input has been completed:
import * as React from 'react';
import { TextInput, View, StyleSheet, Alert } from 'react-native';
import Constants from 'expo-constants';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default function App() {
let timer = React.useRef();
const [text, setText] = React.useState('');
React.useEffect(() => {
if (text) {
timer = setTimeout(() => {
Alert.alert('TEXT : ' + text);
}, 3000);
}
}, [text]);
return (
<View style={styles.container}>
<Card>
<TextInput
placeholder={'Enter the tetxt'}
onChange={(e) => {
clearTimeout(timer);
setText(e.nativeEvent.text);
}}
/>
</Card>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

How to access onClick action in Material UI Link through keyboard Tab key without using component="button" or href when I use tabIndex in it

After I got the focus on Material UI Link through keyboard tab key using tabIndex, the click action is not working when I hit the enter button. I don't understand why. Can anyone help me with this? Thank you.
sandbox link: https://codesandbox.io/s/material-demo-forked-4evbh?file=/demo.tsx
code:
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from "react";
import { makeStyles, createStyles, Theme } from "#material-ui/core/styles";
import Link from "#material-ui/core/Link";
import Typography from "#material-ui/core/Typography";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
"& > * + *": {
marginLeft: theme.spacing(2)
}
}
})
);
export default function Links() {
const classes = useStyles();
const [state, setState] = React.useState(true);
const handleClick = () => {
setState(!state);
};
return (
<Typography className={classes.root}>
<Link onClick={handleClick} tabIndex={0}>
Link
</Link>
<Typography>Click on above link to display hidden content..</Typography>
{state ? "" : "focus on Link using Tab key?"}
</Typography>
);
}
Set component prop to button as follows:
export default function Links() {
const classes = useStyles();
const [state, setState] = React.useState(true);
const handleClick = () => {
setState(!state);
};
return (
<Typography className={classes.root}>
<Link onClick={handleClick} tabIndex={0} component="button">
Link
</Link>
</Typography>
);
}
I have used onKeyPress attribute to achieve the click action through keyboard tab key without using component="button" or href like below.
function goToDetails(event, id)
{
if(event.key === 'Enter'){
event.preventDefault();
history.push(`/`);
}
else {
event.preventDefault();
history.push(`/`);
}
}
<Link tabIndex={0} onKeyPress={(event) => goToDetails(event, row.id)} onClick={(event) => goToDetails(event, row.id)}>
Go to details
</Link>

waitForEvent is not finding the DOM change after fireEvent is called

I have the following component that I'm trying to test with react-testing-library:
const PasswordIconButton = ({
stateString
}) => {
const { state, dispatch } = useContext(Store);
const showPassword = getObjectValue(stateString, state);
const toggleShowPassword = event => {
event.preventDefault();
dispatch(toggleBoolean(stateString, !showPassword));
};
return (
<Layout
showPassword={showPassword}
toggleShowPassword={toggleShowPassword}
/>
);
};
export default PasswordIconButton;
const Layout = ({
showPassword,
toggleShowPassword
}) => {
return (
<IconButton onClick={toggleShowPassword} data-testid="iconButton">
{showPassword ? (
<HidePasswordIcon data-testid="hidePasswordIcon" />
) : (
<ShowPasswordIcon data-testid="showPasswordIcon" />
)}
</IconButton>
);
};
This works exactly as intended in production. If the user clicks the button then it calls toggleShowPassword() which toggles the value of boolean const showPassword.
If showPassword is equal to false and the user clicks the button, I can see that the <ShowPasswordIcon /> is removed and <HidePasswordIcon /> appears. Both have the correct data-testid attributes set.
I'm attempting to test the component will the following test:
import React from "react";
import {
render,
cleanup,
fireEvent,
waitForElement
} from "react-testing-library";
import PasswordIconButton from "./PasswordIconButton";
afterEach(cleanup);
const mockProps = {
stateString: "signUpForm.fields.password.showPassword"
};
describe("<PasswordIconButtonIcon />", () => {
it("renders as snapshot", () => {
const { asFragment } = render(<PasswordIconButton {...mockProps} />);
expect(asFragment()).toMatchSnapshot();
});
//
// ISSUE IS WITH THIS TEST:
// ::::::::::::::::::::::::::
it("shows 'hide password' icon on first click", async () => {
const { container, getByTestId } = render(
<PasswordIconButton {...mockProps} />
);
const icon = getByTestId("iconButton");
fireEvent.click(icon);
const hidePasswordIconTestId = await waitForElement(
() => getByTestId("hidePasswordIcon"),
{ container }
);
expect(hidePasswordIconTestId).not.toBeNull();
});
});
The shows 'hide password' icon on first click test always fails and I'm not sure why. The mockProps are definitely correct and work perfectly in production.
What am I missing here?
I figured it out... The issue is that I needed to wrap the component in the context provider as const { state, dispatch } = useContext(Store); won't work properly without it.
So I changed the render to:
const { container, getByTestId } = render(
<StateProvider>
<PasswordIconButton {...mockProps} />
</StateProvider>
);`
And now the test passes fine.

Preventing users from entering non-digits in input text field with React native

I dont want to allow user to type the alphabets in the input as per the same functionality of keypressevent of jquery/javascript.
you should use a TextInput Component white the prop keyboardType = {"number-pad"}
import { TextInput } from "react-native";
then use it as
<TextInput
keyboardType = {"number-pad"}
// add more props ...
/>
for all the props you can add see this link
Try replace method in JS by replacing non alphabet character with empty string.
Code
import React, { Component } from 'react';
import { AppRegistry, TextInput } from 'react-native';
export default class UselessTextInput extends Component {
constructor(props) {
super(props);
this.state = { inputText: '' };
}
onChanged (text) {
this.setState({
inputText: text.replace(/[A-Za-z]/g, ''),
});
}
render() {
return (
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1, marginTop: 200}}
onChangeText={(text)=> this.onChanged(text)}
value={this.state.inputText}
/>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => UselessTextInput);
You can check by using the isNaN() JS built-in function in your input to prevent the user to type alphabet letters;
const Text = "hello";
const Number = "1234";
console.log(isNaN(Text)) // true
console.log(isNaN(Number)) // false