react- Autocomplete/Textfield not rendering due to maximum update depth exceeded? - javascript

My textfield/autocomplete field is not rendering on my page. I have wrapped react-hook-form around it to help me control the form.
Here the error I get from my console:
index.js:1 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at Controller
Here is my autocomplete form, I cant seem to find any help about this on other threads,
<form noValidate onSubmit={handleSubmit(data => setData(data))}>
<Controller
render={({ onChange, ...props }) => (
<Autocomplete
className={classes.container}
id="stock_list"
name="stock_list"
multiple
options={inputOptions.companies}
filterOptions={filterOptions}
filterSelectedOptions
getOptionLabel={(option) => option.symbol}
getOptionSelected={(option, value) => option.symbol === value.symbol}
renderOption={(option) =>
{
return (
<>
<span style={{ fontWeight: 500, fontSize: "20px", paddingRight: "1rem" }}>{option.symbol}</span><span style={{ color: "#C6C6C6", fontSize: "24px" }}> | </span><span style={{ paddingLeft: "1rem" }}>{option.company}</span>
</>
)
}}
renderInput={(params) => (
<TextField
{...params}
style={{ alignItems: 'center' }}
id="stock_list"
name="stock_list"
variant="outlined"
label="Companies"
className={classes.container}
component={TextField}
/>
)}
/>
)}
name="stock_list"
onChange={([event, data]) => {
return data;
}}
control={control}
defaultValue=""
/>
</form>
How did I structure my <Controller> <Autocomplete> and or <TextField> wrong here?
edit: Here is how im getting my inputOptions
const [inputOptions, setInputOptions] = useState({ companies: [] });
useEffect(() =>
{
Axios.get("https://app.stockbuckets.io/tickers/").then((res) =>
{
setInputOptions({ companies: res.data });
});
}, [setInputOptions]);

Change the dependency array in your useEffect to [inputOptions] and not [setInputOptions], that should help at least.

Related

How to Set Value in Formik from custom component in react native

i have made custom component from react native picker and want to update value in formik when i change it but it say undefined variable setFieldValue when i pass it in my custom component prop as callback function how can i set formik value from my custom component below is my custom compoment which i have imported in formik page
<Formik
initialValues={{
calltype: '',
callfrom: '',
callto: '',
calldate: '',
joinedby: [],
tripinfo: {},
additionalinfo: '',
autoaccept: null,
}}
// validationSchema={CallValidationSchema}
onSubmit={(values, {setSubmitting, resetForm}) => {
setSubmitting(false);
sendValues(values);
}}>
{({
submitForm,
handleBlur,
touched,
errors,
values,
handleChange,
}) => (
<View>
<ARow
row
justifyContent="space-between"
alignItems={'flex-end'}>
<ACol col={6}>
<Picker
callbeck={getdata}
fieldname="calltype"
data={pickerdata}
inputBgColor="#F5F5F5"
heading="Call Type"
placeholder={'Select Call Type'}
onerror={false}
color={'#A9A9A9'}
value={values.calltype}
/>
{errors.calltype && touched.calltype ? (
<AText color={'red'} pb={'5px'}>
{errors.calltype}
</AText>
) : null}
</ACol>
<ACol col={6}>
<AText xtrasmall right>
#1100669
</AText>
</ACol>
</ARow>
</View>
)}
</Formik>
const CustomPicker = ({
<Picker
style={{
color: color ?? '#0D4D8D',
margin: -16,
height: 68,
marginRight: -12,
marginLeft: -4,
}}
selectedValue={selected}
onValueChange={(itemValue, itemIndex) => {
callbeck(fieldname, itemValue);
setSelected(itemValue);
}}>
<Picker.Item style={{fontSize: 12}} value="" label={placeholder} />
{!isEmpty(data) &&
data.map(item => (
<Picker.Item
style={{fontSize: 12}}
label={item.name}
value={item.id}
/>
))}
</Picker>
);
};
Ok Issue is Solved i have not destructured formik properly thats why its saying undefined variable setFieldValue,now when i send setFieldValue function in prop it works..

Display data based on response code from server after loader is loader is completed inside JSX?

I'm using react and redux-toolkit to call the backend API. I have create initial state like
const initialState = {
sessionInfo: {},
loading: false
};
export const validateSession = createAsyncThunk(
'merchant/validate',
async (params, {dispatch}) => {
const data = {
type : "",
source : "",
}
const res = await SessionValidate.validateSession(data)
if(res.status === 200) {
return res.data
}
}
)
const sessionValidation = createSlice({
name:"sessionValidation",
initialState,
extraReducers: {
[validateSession.fulfilled]: (state, { payload }) => {
state.sessionInfo = payload
state.loading = false
},
[validateSession.pending]: (state, { paylaod }) => {
state.loading = true
},
[validateSession.rejected]: (state, { paylaod }) => {
state.loading = false
}
}
})
Now, I fetch the store data from one of the react component to display the loader and data.
I already written working JSX code for my desired output.
NOW THE PROBLEM STATEMENT
Redux-tookit's extrareducers have this lifecycle of fulfilled, reject , pending. Now, on pending state the loader state becomes TRUE. That point the loader component needs to fireup inside JSX.
Later, request got fulfilled and response is saved inside sessionInfo object and loader becomes false.
Now my designed output should be.
Show loader on api startup and once api request is completed, remove loader from jsx and check the code inside response object and display content accordingly.
Everthing works fine, can i refactor the below JSX to properly maintain code.
export default function HomePage() {
const dispatch = useDispatch();
const { sessionInfo, loading } = useSelector(state => state.session)
const nextPath = (path) => {
this.props.history.push(path);
};
React.useEffect(() => {
dispatch(validateSession())
}, [])
const sessionValidation = (
<>
{ loading ?
<Box textAlign="center" sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<CircularProgress size={25} sx={{ mr: 2 }} />
<Typography variant="h4">Validating session.. please wait</Typography>
</Box> :
<Box textAlign="center" sx={{ justifyContent: 'center', alignItems: 'center' }}>
{ sessionInfo && sessionInfo.code === 403 ?
<>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<ErrorIcon fontSize="large" sx={{ mr: 1 }} color="error" />
<Typography variant="h4">{"SESSION EXPIRED" }</Typography>
</div>
<Typography sx={{ textAlign: "center", mt: 2 }}>
<Button component={Link} to = "/home" variant="contained" color="primary">
Go back
</Button>
</Typography>
</>
:
<>
<div>
<CheckCircleIcon sx={{ mr: 1 }} color="success" />
<Typography>{"SESSION VALIDATION SUCCEEDED" }</Typography>
</div>
<Typography sx={{ textAlign: "center", mt: 2 }}>
<Link to = "/home">Get Started</Link>
<Button component={Link} to = "/home" variant="contained" color="primary">
Get Started
</Button>
</Typography>
</>
}
</Box>
}
</>
)
return (
<Container maxWidth="sm" sx={{ mt: 4 }}>
<Paper elevation={1} sx={{ py: 4, borderTop: "4px solid #F76E40" }}>
{ sessionValidation }
</Paper>
</Container>
);
}

setValue does not work when using react-hook-form and react-dropzone

When using react-hook-form and react-dropzone, the form parameter is not updated after setValue.
The setValue set for onDrop does not register a value.
If the first argument of setValue is entered as an appropriate string, the value is set, but if the first argument is the name attribute of the form received from props (e.g., aaaaa), the value is set.
Please let me know how to solve this problem.
export default function FileUpload(props:Props){
return (
<Controller
control={props.control}
name={props.name}
render={({ field: { onChange, onBlur,value }}) => (
<Dropzone
noClick
onDrop={(acceptedFiles) => {
console.log(props.setValue);
props.setValue(props.name, acceptedFiles[0]);
}}
>
{({
getRootProps,
getInputProps,
open,
isDragActive,
acceptedFiles,
}) => (
<div>
<div
style={{
borderStyle: 'dashed',
backgroundColor: isDragActive ? `#808080` : 'transparent',
}}
{...getRootProps()}
>
<Input
type={"hidden"}
{...getInputProps({
// type: 'hidden',
// id: 'spreadsheet',
onBlur,
onChange,
})}
/>
<Stack className={"mx-1 mt-1"}>
<PrimaryButton type="button" onClick={open}>
ファイルを選択
</PrimaryButton>
<Typography fontSize={15}>またはドラッグ&ドロップ</Typography>
<Typography fontSize={15}>{acceptedFiles.length!==0&&acceptedFiles[0].name}</Typography>
</Stack>
</div>
{props.errors && props.name in props.errors && <Typography className={"mt-1.5 ml-3 text-xs"} color={'#d32f2f'}>{props.errors && props.errors[props.name]?.message}</Typography>}
</div>
)}
</Dropzone>
)}
/>
);
}
I think you can use the onChange func coming from the props of the controller.
onDrop={(acceptedFiles) => onChange(acceptedFiles[0])

How to get my Autocomplete input field to reset DefaultValue after submit?

How can I get my <TextField> inside Autocomplete to reset it's default value after form submit?
Currently, the state of formValues during submit remains as the default value?
I've tried to fix the onSubmit function of my form to clear the state of the values, but not able to do so.
How can I clear the value after a user submits?
const { control, handleSubmit } = useForm();
const [formValues, SetFormValues] = useState()
const onSubmit = (data, e) =>
{
console.log(data);
axiosInstance
.patch(URL + slug + '/', {
stock_list: data.stock_list.map(list=>list.symbol),
})
.then((res) =>
{
getFinData(dispatch)(slug);
SetFormValues([''])
console.log(formValues)
});
};
console.log(formValues)
return (
<Container component="main" maxWidth="md">
<div className={classes.container}>
<Grid>
<form noValidate onSubmit = { handleSubmit(onSubmit) }>
<Controller
render={({ onChange ,...props }) => (
<Autocomplete
{...props}
className={classes.inputBar}
id="stock_list"
key={formValues}
name="stock_list"
multiple
options={options}
ListboxComponent={ListboxComponent}
renderGroup={renderGroup}
filterOptions={filterOptions}
filterSelectedOptions
// onChange={(e) => onChange(e.target.value)}
onChange={(e, data) => { onChange(data); SetFormValues(data) }}
getOptionLabel={(option) => option.symbol}
getOptionSelected={(option, value) => option.symbol === value.symbol}
renderOption={(option) =>
{
return (
<>
<span style={{ fontWeight: 500, fontSize: "20px", paddingRight: "1rem" }}>{option.symbol}</span><span style={{ color: "#C6C6C6", fontSize: "24px" }}> | </span><span style={{ paddingLeft: "1rem" }}>{option.company}</span>
</>
)
}}
renderInput={(params) => (
<Zoom in={tabSwitch === 0}>
<TextField
{...params}
style={{ alignItems: 'center' }}
id="stock_list"
name="stock_list"
variant="outlined"
label="Companies"
className={classes.inputBar}
defaultValue={formValues}
/>
</Zoom>
)}
/>
)}
name="stock_list"
control={control}
defaultValue={formValues}
// onChange={([, data]) => data}
/>
{formValues && formValues.length > 0 &&
<Button
variant="contained"
color="primary"
type="submit"
style={{display:"flex",alignItems: 'center',justifyContent:"center"}}
>
Add Stocks
</Button>
}
</form>
</Grid>
</div>
</Container>
);
})
UPDATE:
I have tried implementing your codes but still no success in removing the data from original state?
const [formValues, SetFormValues] = useState([])
const onSubmit = (data, e) =>
{
console.log(data);
axiosInstance
.patch(URL + slug + '/', {
stock_list: data.stock_list.map(list=>list.symbol),
})
.then((res) =>
{
getFinData(dispatch)(slug);
SetFormValues([]);
});
};
return (
<Controller
render={({ onChange ,...props }) => (
<Autocomplete
{...props}
className={classes.inputBar}
id="stock_list"
key={formValues}
name="stock_list"
multiple
options={options}
ListboxComponent={ListboxComponent}
renderGroup={renderGroup}
filterOptions={filterOptions}
filterSelectedOptions
onChange={(e, data) => { onChange(data); SetFormValues(data) }}
getOptionLabel={(option) => option.symbol}
getOptionSelected={(option, value) => option.symbol === value.symbol}
renderOption={(option) =>
{
return (
<>
<span style={{ fontWeight: 500, fontSize: "20px", paddingRight: "1rem" }}>{option.symbol}</span><span style={{ color: "#C6C6C6", fontSize: "24px" }}> | </span><span style={{ paddingLeft: "1rem" }}>{option.company}</span>
</>
)
}}
renderInput={(params) => (
<Zoom in={tabSwitch === 0}>
<TextField
{...params}
style={{ alignItems: 'center' }}
id="stock_list"
name="stock_list"
variant="outlined"
label="Companies"
className={classes.inputBar}
defaultValue={formValues}
value={formValues}
/>
</Zoom>
)}
/>
)}
name="stock_list"
control={control}
defaultValue={[]}
/>
It might be worth noting that my Mui AutoComplete and textfield is wrapped around by React Hook Form controller.
There is error in your code.
When using state, specify the data type to be stored.
E.g
if you are storing array of data, your state should be const [formValues, SetFormValues] = useState([]); not const [formValues, SetFormValues] = useState();
if you are storing string of data, your state should be const [formValues, SetFormValues] = useState(""); not const [formValues, SetFormValues] = useState();
if you are storing integer of data, your state should be const [formValues, SetFormValues] = useState(0); not const [formValues, SetFormValues] = useState();
To clear the state of each of these data
For Array
SetFormValues([]);
For String
SetFormValues("");
For Int
SetFormValues(0);
So correct your code and ty again. It will work for you.
put this code in the then callback of axios SetFormValues([]);
Because defaultValue is default value..
Try looks like this; (add value)
<TextField
style={{ alignItems: 'center' }}
id="stock_list"
name="stock_list"
variant="outlined"
label="Companies"
defaultValue={formValues}
value={formValues}
/>
https://material-ui.com/api/input/#main-content
defaultValue: The default input element value. Use when the component is not controlled.
value: The value of the input element, required for a controlled component.
You can do it this way
const [formValues, SetFormValues] = useState(null)
Put this code in the then callback of axios SetFormValues(null);
OR
const [formValues, SetFormValues] = useState([])
Put this code in the then callback of axios SetFormValues(null);
If any of those two above does not work for you, try storing the values as string in state
E.g const [formValues, SetFormValues] = useState("")
and clear items using SetFormValues(null) or SetFormValues("");

ReactJs :Error: Maximum update depth exceeded. React limits the number of nested updates to prevent infinite loops

Whenever i am adding the if(IsLogged()){...} block I am getting this error.
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.
React limits the number of nested updates to prevent infinite loops.
I've read other similar question here but I'm not able to understand whatI'm doing wrong.
I'm a newbie to React Js so please bear with me.
render() {
if (IsLogged()) {
return <Redirect to="/" />;
}
return (
<Grid
textAlign="center"
style={{ height: "75vh" }}
verticalAlign="middle"
>
<Grid.Column style={{ maxWidth: 450 }} columns={2}>
<Segment>
<Grid.Row>
<Header as="h1" color="teal" textAlign="center">
Log In
</Header>
</Grid.Row>
<Form
onSubmit={this.submitLogin}
style={{ paddingTop: "1rem" }}
>
<Form.Input
icon="mail"
iconPosition="left"
placeholder="Email"
fluid
value={this.state.email}
onChange={(e) =>
this.setState({ email: e.target.value })
}
/>
<Form.Input
icon="lock"
iconPosition="left"
fluid
placeholder="Password"
type="password"
value={this.state.password}
onChange={(e) =>
this.setState({
password: e.target.value,
})
}
/>
<Button color="teal" fluid size="large">
Log In
</Button>
</Form>
<Grid.Row style={{ paddingTop: "1rem" }}>
<div style={{ marginTop: "1rem" }}>
Not Singed In Yet?
<Link to="/signup">Sign Up</Link>
</div>
</Grid.Row>
</Segment>
</Grid.Column>
</Grid>
);
function IsLogged() {
let token = sessionStorage.getItem("jwtToken");
if (!token || token === ""|| token === null || typeof token ==="undefined") {
return false;
} else {
return true;
}
}
export default IsLogged;
Try changing your onChange handlers to include e.preventDefault(); https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault
onChange={(e) => {
e.preventDefault();
// setState here
}
}
This error also might happen when you are using setState() in render block, and then it causes infinite rerender. What is inside your isLogged() function? Most probably you should check is user logged with true/false variable, neither executing a function in render block, that might cause infinite loop
I am not sure what is your IsLogeed method ? But try with ...
if (!IsLogged()) {
return <Redirect to="/" />;
}

Categories