How to use 2 functions in an onBlur with ui material? - reactjs

I'm using the material ui library, and in the onBlur input event I'm adding 2 events, one that is coming by props and another is declared in the same component.
onBlur={(props.onBlur, validation)}
but he only recognizes me for the second event that happened to him.
It is not recognizing me the two events that are in onBlur.
import React, { useState } from "react";
import FormControl from "#material-ui/core/FormControl";
import FormHelperText from "#material-ui/core/FormHelperText";
import Input from "#material-ui/core/Input";
import InputLabel from "#material-ui/core/InputLabel";
export default function CustomInputExample(props) {
const [validationValue, setValidation] = useState(false);
const validation = () => {
if (props.value === "") setValidation(true);
else setValidation(false);
};
return (
<FormControl>
<InputLabel htmlFor={props.name}>{props.labelText}</InputLabel>
<Input
name={props.name}
aria-describedby="component-helper-text"
type="text"
onChange={props.onChange}
onBlur={(props.onBlur, validation)}
value={props.value}
/>
{props.required !== undefined && validationValue ? (
<FormHelperText id={props.name}>Required field</FormHelperText>
) : null}
</FormControl>
);
}
I need to use those two events in onBlur.

You can call 2 function using an anonymous function,
onBlur={() => {
props.onBlur();
validation();
}}

Related

React DateTimePicker showing required error even after select the value in datepicker

React DateTimePicker is showing required error even after selecting a value in DatePicker:
const validationForm = Yup.object().shape({
DateTime:Yup.date().required('Date and time is required')
});
<DateTimePicker {...register('DateTime')}/>
Here the register function from react form hook form might not support the 3rd party library react datetimepicker.
For these types of components, we can use the Control component from react hook form to wrap the custom component for the validations.
For ex.
import React from "react";
import ReactDatePicker from "react-datepicker";
import { TextField } from "#material-ui/core";
import { useForm, Controller } from "react-hook-form";
function App() {
const { handleSubmit, control } = useForm();
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<Controller
control={control}
name="ReactDatepicker"
render={({ field: { onChange, onBlur, value, ref } }) => (
<ReactDatePicker
onChange={onChange}
onBlur={onBlur}
selected={value}
/>
)}
/>
<input type="submit" />
</form>
);
}
For more information refer to the official docs from react hook form.
React Hook form Control

React - A component is changing a controlled input to be uncontrolled (Custom Control)

I am new to react and i ran into this error while creating a custom form control, does anyone know why this is happening and how to solve it?
error:
Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info:
code:
import React from "react";
import { TextField, Grid } from "#material-ui/core";
import { useFormContext, Controller } from "react-hook-form";
const FormInput = ({ name, label, required }) => {
const { control } = useFormContext();
return (
<Grid item xs={12} sm={6}>
<Controller
render={({ field }) => (
<TextField fullWidth label={label} required={required} {...field} />
)}
control={control}
name={name}
/>
</Grid>
);
};
export default FormInput;

Validate for Material UI Input without using Formik ValidationSchema

I'm trying to add simple custom validation (non-empty or minimum characters) to a MUI TextField that is part of React functional component using the Formik useField hook. This reusable component will be a part of Formik form in it's parent component. The use of this functional child component is for it to be a reusable component and so the validation for the Textfield should occur within the component instead of the ValidationScheme attribute in the parent component's Formik tag since the form is not predefined. How can I add this custom validation to the TextField within the child component?
import React from 'react';
import { useField } from "formik";
import { TextField, TextFieldProps } from '#material-ui/core';
type FormikTextFieldProps = {
formikKey: string,
} & TextFieldProps
const FormikTextField = ({ formikKey, ...props }: FormikTextFieldProps) => {
const [field, meta, helpers] = useField(formikKey);
const validate = () => {
if(!field.value){
helpers.setError('The field is empty')
}
}
return (
<>
<TextField
id={field.name}
name={field.name}
helperText={meta.touched ? meta.error : ""}
error={meta.touched && Boolean(meta.error)}
value={field.value}
onChange={field.onChange}
{...props}
/>
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</>
)
}
export default FormikTextField

UseEffect and useCallback still causes infinite loop in react project

I can't seem to resolve an infinite loop issue in my react project.
I'm working on a daily-log react app. Let me explain the project briefly. Here is the picture of the code for quick view:
The same code is available at the bottom.
The structure (from top to bottom)
The DailyLog component has a form that uses Question components into which props are passed.
The Question component uses the props to display a question and description. It also contains an Input component into which props are further passed down.
The Input component takes the props and renders the appropriate form input field.
The logic (from bottom to top)
The Input component handles it's own inputState. The state is changed when the user inputs something and the onChangeHandler is triggered.
The Input component also has a useEffect() hook that calls an onInput() function that was passed down as props from DailyLog.
The onInputHandler() in the DailyLog component updates the formState which is the form-wide state containing all input field values. The formState is amended depending on which input field is filled at the time.
The onInputHandler() uses the useCallback() hook which is supposed to stop an infinite loop caused by any parent/child re-renders. But it doesn't work :frowning:
What's wrong in the code? What am I missing here? Code provided below:
//DailyLog.js
import React, { useState, useCallback } from 'react';
import Question from '../components/FormElements/Question';
import questionData from '../components/DailyLog/questionData';
import './DailyLog.css';
const DailyLog = () => {
const [formState, setFormState] = useState();
const onInputHandler = useCallback(
(inputId, inputValue) => {
setFormState({
...formState,
[inputId]: inputValue,
});
},
[formState]
);
return (
<main className="container">
<form action="" className="form">
<Question
id="title"
element="input"
type="text"
placeholder="Day, date, calendar scheme"
onInput={onInputHandler}
/>
<Question
id="focus"
question={questionData.focusQuestion}
description={questionData.focusDescription}
element="textarea"
placeholder="This month's focus is... This week's focus is..."
onInput={onInputHandler}
/>
</form>
</main>
);
};
export default DailyLog;
//Question.js
import React from 'react';
import Input from './Input';
import './Question.css';
const Question = props => {
return (
<div className="form__group">
{props.question && (
<label className="form__label">
<h2>{props.question}</h2>
</label>
)}
<small className="form__description">{props.description}</small>
<Input
id={props.id}
element={props.element}
type={props.type}
placeholder={props.placeholder}
onInput={props.onInput}
/>
</div>
);
};
export default Question;
//Input.js
import React, { useState, useEffect } from 'react';
import './Input.css';
const Input = props => {
const [inputState, setInputState] = useState();
const { id, onInput } = props;
useEffect(() => {
onInput(id, inputState);
}, [id, onInput, inputState]);
const onChangeHandler = event => {
setInputState(event.target.value);
};
// check if question element type is for input or textarea
const element =
props.element === 'input' ? (
<input
id={props.id}
className="form__field"
type={props.type}
value={inputState}
placeholder={props.placeholder}
onChange={onChangeHandler}
/>
) : (
<textarea
id={props.id}
className="form__field"
rows="1"
value={inputState}
placeholder={props.placeholder}
onChange={onChangeHandler}
/>
);
return <>{element}</>;
};
export default Input;
Remove id and onInput from useEffect sensivity list
useEffect(() => {
onInput(id, inputState);
}, [inputState]);
And set default value of inputState to '' as follow:
const [inputState, setInputState] = useState('');
To prevent 'A component is changing an uncontrolled input of type text to be controlled error in ReactJS'. Also you can init formState:
const [formState, setFormState] = useState({title:'', focus:''});

How to persist intermittent text on `react-select`?

I use below code which is to render a multi selection react-select component. But what I found is that when I type any characters and leave the focus before select any items, the characters are not persisted.
import React from 'react';
import Select from 'react-select';
import makeAnimated from 'react-select/animated';
import { colourOptions } from '../data';
const animatedComponents = makeAnimated();
export default function AnimatedMulti() {
return (
<Select
closeMenuOnSelect={false}
components={animatedComponents}
defaultValue={[colourOptions[4], colourOptions[5]]}
isMulti
options={colourOptions}
/>
);
}
As an example of that, see below screenshot. I typed f and move the focus on other component. Then the f will be removed from the select component. Is there a way to persist the f when it loses focus?
You can achieve this by combining inputValue, value, onInputChange and onChange props.
Something like this
<Select
value={this.state.value}
onChange={value => this.setState({ value })}
inputValue={this.state.inputValue}
onInputChange={inputValue => this.setState({ inputValue })}
/>
You can read more about this in the docs

Resources