The thing is, you have to find a small analyze between function that return elements which takes arguments and functional component that returns elements which takes props.
Consider the below example :
//here is the difference, when you use function, function takes arguments as it is.
const UpdateIcons = (products) => {
// if you use this as component props will be like products props will return the products object again, here you have to use {products} destructuring or products.propducts["One"]
//like this const UpdateIcons = ({products}) => {
if((products["One"] === "A") && (products["Two"] === "B") && (products["Three"] === "C") ) {
return <p>Conditional</p>
}
return <p>Show Always</p>
}
class MyIssue extends Component {
render() {
const { products } = this.props;
return (
<div>
{UpdateIcons(products)}
{/*passing arguments here products will be {"One": "A", "Two": "B"}*/}
<UpdateIcons products={products} />
{/* passing props , props will be same as products */}
</div>)
}
}
class App extends Component {
constructor() {
super();
this.state = {
products: {
"One": "A",
"Two": "B",
"Three": "C"
}
};
}
render() {
return <MyIssue products={this.state.products} />
}
}
working demo
Answer from Jayavel on Stack OverflowThe useRef hook is not just for DOM refs, but can store any mutable value you like.
Example
function FunctionalBar(props) {
const [foo] = useState(new Animated.Value(0));
const _foo = useRef(0);
function showFoo() {
let anim = Animated.timing(foo, { toValue: 1, duration: 1000, useNativeDriver: true });
anim.start(() => console.log(_foo.current));
}
useEffect(() => {
function _onChangeFoo({ value }) {
_foo.current = value;
}
foo.addListener(_onChangeFoo);
showFoo();
return () => foo.removeListener(_onChangeFoo);
}, []);
return <View />;
}
You can use useRef hook (it's the recommended way stated in docs):
- Declaring variable:
const a = useRef(5) // 5 is initial value - getting the value:
a.current - setting the value:
a.current = my_value
reactjs - React Function component setting state variable V/s using local variable - Stack Overflow
reactjs - best way for local variables in functional component react native - Stack Overflow
React functional component reinitialises local functions and variables on re render (React Hooks)
How to set local variable value as state
It seems you are wanting to compute a myTitle value based on some prop or context value being passed to the component. Storing passed props/context values in local state is generally considered anti-pattern in React. Compute the myTitle value and pass it along to the child component.
const MyComponent = () => {
const myTitle = someContextApiObj.value === "XYZ" ? "XYZ" : "ABC";
return <ChildComponent myTitle={myTitle} />;
};
If the myTitle value is an expensive calculation or you just want to provide a stable reference to children, use the useMemo hook to provide this.
useMemo
import { useMemo } from 'react';
const MyComponent = () => {
const myTitle = useMemo(() => {
return someContextApiObj.value === "XYZ" ? "XYZ" : "ABC";
}, [someContextApiObj]);
return <ChildComponent myTitle={myTitle} />;
};
Your code runs into an infinite loop because of your if-clause. If you set the title and the condition doesn't change, it will get set on every rerender causing a new render - infinite chain of rerenders.
Using a state offers you the ability to change the value conditionally, while using a local variable not coupled to a state makes the variable constant.
I had the same concerns as well when I first saw the proposal, but this was addressed in the React Docs Hooks Proposal FAQ:
Are Hooks slow because of creating functions in render?
No. In modern browsers, the raw performance of closures compared to classes doesn’t differ significantly except in extreme scenarios.
My takeaway is that although you have additional overhead now in the repeated declarations per render, you have additional wins elsewhere:
Hooks avoid a lot of the overhead that classes require, like the cost of creating class instances and binding event handlers in the constructor.
Idiomatic code using Hooks doesn’t need the deep component tree nesting that is prevalent in codebases that use higher-order components, render props, and context. With smaller component trees, React has less work to do.
Overall the benefits might be more than the downsides which makes hooks worth using.
You can always simplify the code to take functions out so that they aren't initialised always, by passing the required values as constants.
import React, { useState } from "react";
function doSomething (counterState, incrementCounterState){
// does something and then calls incrementCounterState
// with the updated state.
}
function Counter() {
const [counterState,incrementCounterState] = useCommontState(0);
return (
<div>
<p>{counterState}</p>
<button onClick={incrementCounterState}>increase</button>
....
.... // some jsx calling local scoped functions.
....
</div>
);
}
function increment(defaultValue, setState){
setState(defaultValue + 1);
}
function useCommontState(defaultValue){
var [state, setState] = useState(0);
return [state, increment]
}
export default Counter;
Also in my opinion the function design being suggested in all the demos and docs is for people to get comfortable with it and then think about the re-initialization aspects. Also the cost that re-initialization would significanly be overpowered by the other benefits that it provides.
Hey, I'm working on this code as side project. Mapping employ gives me data._id but when I update state in render it gives Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop and I can't set state outside render because it is in local scope. So, I want to update state with data._id when edit button is clicked.
I'm using hooks for this and setId is the useState setter.
{employ.map(data => (
<EuiFlexGroup gutterSize="l" >
<EuiFlexItem className="items_menu-item_title">
<EuiCard
title={data.company}
description={data.position}
/>
<EuiButton
color="danger"
size="s"
className="btn btn-outline-danger"
>
Delete
</EuiButton>
<EuiButton
color="danger"
size="s"
className="btn btn-outline-success"
onClick={formedit}
onClick={setId(data._id)}
>
Edit
</EuiButton>
</EuiFlexItem>
<br />
</EuiFlexGroup>
))}The reason is if you useState it re-renders the view. Variables by themselves only change bits in memory and the state of your app can get out of sync with the view.
Compare this examples:
function Foo() {
const [a, setA] = useState(0);
return <div onClick={() => setA(a + 1)}>{a}</div>;
}
function Foo() {
let a = 0;
return <div onClick={() => a = a + 1}>{a}</div>;
}
In both cases a changes on click but only when using useState the view correctly shows a's current value.
Local variables will get reset every render upon mutation whereas state will update:
function App() {
let a = 0; // reset to 0 on render/re-render
const [b, setB] = useState(0);
return (
<div className="App">
<div>
{a}
<button onClick={() => a++}>local variable a++</button>
</div>
<div>
{b}
<button onClick={() => setB(prevB => prevB + 1)}>
state variable b++
</button>
</div>
</div>
);
}
Is there some benefit to using useRef vs a local variable, especially in case where it's not intended to be shared between multiple instances of the same component.
In this example, it's being used to keep track of a timer that's perhaps cleared and reassigned with new timers in other places in the component.
Will timer2 be reassigned to null when stateItem changes and triggers a render?
const myComponent = ({stateItem}) => {const timer1 = useRef(null);let timer2 = null;useEffect(() => {timer1.current = setTimeout(()=> { }, 1000);timer2 = setTimeout(() => { }, 10000);return () => {clearTimeout(timer1.current);clearTimeout(timer2);};// other component stuff}, [stateItem]);
You could have it be a state variable, but that wouldn't make much sense since the state is meant to hold variables that relate to the current state of the UI. Also, state variables are meant to trigger a re-render if they are updated (with setState()).
Neither of these would make much sense for a timer ID to be stored in the state. In other words, it's not a state variable because:
- The timerID doesn't express the representation of the UI in any way.
- Updating the timerID shouldn't trigger a re-render.
The official docs actually mention this:
The state contains data specific to this component that may change over time. [...] If you don't use it in
render(), it shouldn't be in the state. For example, you can put timer IDs directly on the instance.
Well, you can store timerID in state, but this is not a good practice, as you can
read in the same documentation page:
If you don't use something in render(), it shouldn't be in the state.
Every time that you update your state via setState, render method is invoking. So if this data doesn't change UI, then calling render method doesn't change anything and it will be a waste.
That is why all the 'helper' data, such as API requests, e.t.c is better to store as component-object keys.
Wondering what's the best way to do this. Let's say we're making a post component, and for each post component there are things that will change (likes, comments) and things that will never change (url, image). I'm currently getting all my data through an api call with useEffect and inside the useEffect hook I use my state hooks to set my variables that will be updating throughout the duration of the post. I could put url and image in a useState hook and just never change it again, but is that the best way to do it? I tried doing let url = data.url inside my useEffect but I don't think that was working correctly