Hello I'm trying to export exportTest to another js file and do re-render. I'm trying it like this
import React, { useState } from 'react';
import { StyleSheet, View } from 'react-native';
var n;
export var exportTest;
function foo()
{
//doing something and giving back n as 1 or 0
}
export default function App () {
const [test,setTest] = useState();
if(n == 0)
{
//doing something
setTest('n is zero')
}
else
{
//doing something
setTest('n is not zero')
}
exportTest=test
return(
<View>
...
...
...
</View>
);
}
I'm getting error too meny re-renders, because I'm doing setTest in if
How can I do setTest once in last line of if? n is changing in some function, I'm getting it as 1 or 0.
And this is how I'm importing exportTest in another file import {exportTest} from './App.js';
import React, { useState } from 'react';
import { StyleSheet, TouchableOpacity, View, Text } from 'react-native';
export const exportTest = () => {
const [test,setTest] = useState();
let n = 0;
if(n == 0)
{
setTest('n is zero')
}
else
{
setTest('n is not zero')
}
exportTest=test
return(
...
...
...
);
}
Try that. You are importing it as a const hence the {exportTest} import you wrote. You need to export exportTest as a const.
There are a lot of things wrong and you deleted the return so your purpose isn't clear. See if that helps. Feel free to comment again. I recommend cleaning up your code.
You're creating an infinite loop. State and prop changes trigger re-render, and in your case - the re-render triggers a state update. That's why state updates should NEVER be a part of your renderer's logic.
From reactjs.org:
What does setState do?
setState() schedules an update to a component’s state object. When
state changes, the component responds by re-rendering
Normally, you would do all your state manipulations on componentDidMount or componentWillReceiveProps, and hook's alternative to those is an Effect Hook.
useEffect(() => {
// componentWillMount
return () => {
// componentWillUnmount
};
});
Trigger on props updates:
useEffect(() => {
// prop abc changed
}, [props.abc]);
Notice, in the latter example I left out the return statement.
https://reactjs.org/docs/hooks-effect.html
Related
I have my App.js re-rendering multiple times. Is there a way to optimize that? <React.StrictMode> is already removed. I also tried without useMemo and having these 3 variables in the array for useEffect.
export default function App() {
const { instance, accounts, inProgress } = useMsal();
const callLogin = useMemo(() => {
return () => {
console.log("Inside callLogin");
const isAuthenticated = accounts.length > 0;
if (!isAuthenticated && inProgress === InteractionStatus.None) {
instance.loginRedirect();
}
};
}, [instance, accounts, inProgress]);
console.log("I'm inside App.js!");
useEffect(() => {
console.log("App.js useEffect");
callLogin();
}, [callLogin]);
return
(<SomeComponent />)
}
This is what it looks like after one hard clean refresh. You can ignore Kendo warnings.
This is how App.js is called in index.js
ReactDOM.render(
<MsalProvider instance={msalInstance}>
<App />
</MsalProvider>,
document.getElementById('root')
);
I removed the entire useEffect hook and this is what I ended up with
Your useMsal hook outputs inProgress state variable which appears to be a boolean flag for the loading state of a promise. These commonly goes from undefined to true to false --- which would cause all sub-components to render 3 times, once for each state change.
Your callLogin() function should be a useCallback with it's dependencies set.
You should also be memoizing your <SomeComponent> using memo() to React when it should be re-rendering that component. Right now, your SomeComponent just renders anytime the state changes.
Try using this:
const MemoizedSomeComponent = memo(({accounts}) => {
console.log('Memoized render accounts =', accounts);
return <span>Hello World</span>
}
export default function App() {
const { instance, accounts, inProgress } = useMsal();
const callLogin = useCallback(() => {
console.log("Inside callLogin");
const isAuthenticated = accounts.length > 0;
if (!isAuthenticated && inProgress === InteractionStatus.None) {
instance.loginRedirect();
}
}, [instance.loginRedirect, inProgress, accounts, InteractionStatus.None]);
console.log("I'm inside App.js!");
useEffect(() => {
console.log("App.js useEffect");
callLogin();
}, [callLogin]);
return <MemoizedSomeComponent accounts={accounts} />;
}
Renders are easier to deal with when your app is broken down into smaller parts. Here's a working sandbox template I created which demonstrates a barebones approach to using useContext, useMemo, useCallback and memo() to avoid re-renders and have better control over your components.
This particular response on Preventing rerenders with React.memo and useContext hook is extremely informative, as well as this entire section on useContext from the React Beta docs which really made things click for me.
i have a react component thats keep re-rendering idk why but i think the reason is the data fetching
data code :
export function KPI_Stock_Utilisation() {
const [kpi_stock_utilisation, setKpi_stock_utilisation] = useState([{}]);
useEffect(() => {
axios.get("http://localhost:5137/KPI_Stock_Utilisation").then((response) => {
setKpi_stock_utilisation((existingData) => {
return response.data;
});
});
}, []);
console.log('data get')
return kpi_stock_utilisation;
}
this log displayed many times , and the log in the component too
component code :
import React from "react";
import { KPI_Stock_Utilisation } from "../../Data/data";
import { useEffect } from "react";
export default function WarehouseUtilisChart(props) {
let kpi_stock_utilisations =KPI_Stock_Utilisation();
let Stock_utilisation = (kpi_stock_utilisations.length / 402) * 100;
console.log('component render')
return (
<div>
<p>{kpi_stock_utilisations}</p>
</div>
);
}
im new with react i tried useEffect inside the componenets but its not working
Calling the react custom hook KPI_Stock_Utilisation several times will for sure render more than once.
in your case I suggest you use useEffect in the same component as I will show you.
import React,{useEffect,useRef} from "react";
import { KPI_Stock_Utilisation } from "../../Data/data";
import axios from 'axios';
export default function WarehouseUtilisChart(props) {
const [kpi_stock_utilisation, setKpi_stock_utilisation] = useState([{}]);
const stock_utilisation= useRef(0);
useEffect(() => {
axios.get("http://localhost:5137/KPI_Stock_Utilisation").then((response) => {
stock_utilisation.current = (response.data.length / 402) * 100;
setKpi_stock_utilisation(response.data);
});
//this will guarantee that the api will be called only once
}, []);
//you should see this twice, one with the value 0, and another one, the calculated data
console.log('component render',stock_utilisation.current)
return (
<div>
<p>{kpi_stock_utilisations}</p>
</div>
);
}
To note, if you call this component from more than one location, for sure it will render several times - keep that in mind.
On the other hand, all your variables should always start with a lower case and try to name your variables like this: instead of kpi_stock_utilisation change it to kpiStockUtilisation for a better coding practice
You got into infinite loop.
Its hard to explain why it doesn't work as expected, but I can try.
First of all, useEffect with empty array of dependencies works like componentDidMount and fires only after (!) first render.
So you have some value returned from your let kpi_stock_utilisations =KPI_Stock_Utilisation(); then it rendered, after this your useEffect fires a request and set state, setting of state trigger re-render and new value to return, this new value trigger your parent component to return let kpi_stock_utilisations =KPI_Stock_Utilisation(); might run again.
If you are trying to create a custom hook for fetching some info, follow rules of hooks
I hope it helped you
I am trying to forcefully rerender the complete component on value change inside the render function.
Below is a sample code to explain my problem. Profile component I am calling after the login and it's called and two functions inside this getting called and the value is set in the state. Now I am on another screen where I am updating mssidnNumber inside the context and that change I can see in the Profile render() function val. let val = this.context.mssidnNumber; and this val value will change on condition so on this basis I am trying to rerender the complete Profile component again so all values will update. How can I do this please help? Is that possible?
import React, { Component } from 'react';
import { View} from 'react-native';
class Profile extends Component {
constructor(props) {
super(props);
}
async componentDidMount() {
this.Profilefunction();
}
Profilefunction = () =>{
this.setState({})
await this.profile2fucntion();
}
profile2fucntion =() => {
}
render() {
let val = this.context.mssidnNumber;
return (
<View>
</View>
);
}
}
export default Profile;
Sorry for the noob question, but I'm a noob in React and I am strugling with this.
I have a file that exports a variable that is being mutated over time. Let's say something like this (not the real code, the variable is changing correctly):
// variable.js
let myVar = 0;
setInterval(() => myVar++, 3000);
export { myVar };
and a react component that has to display the current value:
import React, { Component, Fragment } from "react";
import { myVar } from './variable.js';
export default class myComponent extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Fragment>
<div>{myVar}</div>
</Fragment>
);
}
}
What would be the best approach to get the variable displayed correctly while they change? I have tryied to set is as a state, as a prop and rendering it directly, but I am missing something.
I can not export a getter function, as I don't know from the component when the variable is going to change, but maybe I can change the approach? maybe throwing an event in each change?
Try this, It won't work like the real-time update. But you can access like below
You can create a custom hook, that will update real-time
export default function useUpdate() {
const [myVar, setState] = useState(0)
setTimeout(function () {
setState(myVar++);
}, 3000);
return [myVar, setState];
}
import React, { Component, Fragment } from "react";
import { useUpdate } from './variable.js';
export default () => {
const [myVar] = useUpdate();
return (
<Fragment>
<div>{myVar}</div>
</Fragment>
);
}
I wonder why this gets stuck in infinite renders as soon as I set it's value coming from backend API.
I don't want to stop it using useEffect() as I need to use it to re render after the values have been assigned
CODE :
import React, { useState, useEffect } from 'react';
// import FormCheckLabel from 'react-bootstrap/FormCheckLabel';
import './CheckForms.css';
// import Scrollspy from '../Scrollspy/Scrollspy';
import axios from 'axios';
const CheckForms = () => {
const [menu, setMenu] = useState([]);
const fetchList = async () => {
try {
const res = await axios.get(`http://localhost:5000/api/items`);
const list = res.data.response;
// setMenu(list); // <-- This is causing ulimited renders ! //
} catch (err) {
console.log(err.response);
};
};
fetchList();
console.log("something");
return (
<div>
</div>
)
}
export default CheckForms;
I would really appreciate the help. Thanks.
you cannot place fetchList(); outside useEffect() because,
when component is mounted, fetchList() is called, it sets state and component rerenders.
again fetchList() is executed and again sets state and comoenent again rerenders. it forms an infinite loop.
you must do
useEffect(()=>fetchList(),[])
or execute it on an event
you need useEffect for this. Otherwise fetchList will be called on each re render.
So your infinite loop comes from :
fetchList() => setMenu() => render() => fetchList() => setMenu() and so on ...
I don't want to stop it using useEffect() as I need to use it to re
render after the values have been assigned
useEffect(callback, [triggers]) second parameter is here exactly for that, control when a re render should happen, based on props/state changes