I read the docs about useEffect and understand how it makes life more easier than life cycle methods. Yet I am wondering what would not be possible without useEffect?
E.g. instead of (all code is dummy code)
useEffect(networkRequest.then(update state));
couldn't I just use
// inside functional component
function App() {
networkRequest.then(update state)
}
What do you mean "makes life more easier than lifecycle methods"? React hooks are how you utilize component lifecycle in functional components.
Just like the render lifecycle method of class-based components is to be a pure function without side-effects, so to is the entire body of a functional component. The body of a functional component is the "render" function.
// inside functional component
function App() {
networkRequest.then(update state)
}
The above, as written, has no guard protecting the side-effect of the network request nor state update... it will simply update state and rerender, and update state and rerender, ... ad nauseam, or in other words, infinitely render loop.
React hooks are what allow you to utilize component lifecycle in functional components.
To directly answer your question though:
Yet I am wondering what would not be possible without useEffect?
It would not be possible to trigger side-effects such as any asynchronous network requests, authentication, etc... It wouldn't be possible to invoke any specific when a component mounts or rerenders. It wouldn't be possible to run any specific logic when a specific state/prop value updated.
Related
My components are structured looks like this. Each component is it's own functional component in its own file - this is just a schematic of how they interract.
<FirstLevelComponent>
// propValue is declared on this level with useState hook.
<SecondLevelComponent someProp={propValue}>
<ChildComponent1></ChildComponent1>
<ChildComponent2 someProp={propValue}></ChildComponent2>
<ChildComponent3></ChildComponent3>
</SecondLevelComponent>
</FirstLevelComponent>
someProp is declared in state in the FirstLevelComponent and is passed along to the SecondLevelComponent and when it changes, it triggers the re-render of the entire SecondLevelComponent. But the only dependency on that prop is in one of the children. The rest of the children are unaffected.
What would be the best way to isolate that behavior and only limit scope of re-rendering to the single child that depends on that prop?
Some constraints:
This is a huge production application so something like Just add redux would not be an easy solution.
Refactoring SecondLevelComponent will be a challenge (1500 lines of code), while I am open to such opportunity`, I am looking for the way to achieve this assuming it's not a hello world project. Solutions that are easy and ideal for application in its early stages are quite a rework when we are dealing with legacy code.
and only limit scope of re-rendering to the single child that depends on that prop?
What you're looking to accomplish goes against the nature of React. If a parent component has state, and that state changes, React will react and rerender the component.
Stopping the parent component from rerendering when its state changes is an anti pattern (as opposed to simply stopping its children from rerendering with useMemo).
The way I see it, you have the following options:
Add state to the child component instead. If it's the only component reliant on this state, it should be a simple refactor.
Replace useState with useRef in the parent component. Pass this to the child for creating initial state.
Option two could lead to other implications if anything else in the app is dependant on this piece of state.
Now, if you just want to keep the extra children from rerendering, which isn't exactly what I quoted above from the question, you could just simply use useMemo (and useCallback if passing a function as a prop)..
I saw the same problem, also big application
Option 1
You can take advantage of render from React composition if you can move propValue state and ChildComponent2 component into SecondLevelComponent
Explanation: the states in SecondLevelComponent wont rerender his childs like ChildComponent1 and ChildComponent3
Option 2
You can memoize you components using React.useMemo not React.memo because you are not passing propValue in ChildComponent1 and ChildComponent3 like this:
// How to memoize
const ChildComponent1Memoized = React.useMemo(()=><ChildComponent1/>,[propValue])
// In this case ChildComponent1Memoized will not rerender again
<SecondLevelComponent someProp={propValue}>
{ChildComponent1Memoized} // <---
<ChildComponent2 someProp={propValue}></ChildComponent2>
<ChildComponent3></ChildComponent3>
</SecondLevelComponent>
Extra
if you are passing functions as props be sure you are using useCallbak in every function, because they are rebuilding in every render, that cause Memo dosent work
Using Class-based Components we are able to bind in the state because well, there is a state, thus causing less re-rendering.
Functional Components do not offer this functionality because in order to use state we need Hooks, and with Hooks, the component gets the power of state without having one.
My question is:
When it comes to the overall App, does the use of arrow functions (=>) within Functional Components result into increased re-rendering?
Alright, an arrow function is a short syntax alternative to a regular function expression.They don't have their own bindings to the this, arguments, super, or new.target keywords.
Arrows functions is plain simple ES6, it has nothing to do with react functionality.
In fact, the Component lifecycle in react is affected by state and props.
So, except in the parts where call setState within () => (), the arrow functions HAVE NO direct or indirect impact your component rendering/updating.
I've just created a function component which contains the expression const [state, setState] = useState(). Now that I have access to state and setState(), this stateful function component is very similar to a stateful class component. I'm only aware of two differences between this component and a typical class component: when referring to the state we must use state.handle instead of this.state.handle, and we have easy access to the Context API outside of the render method.
Aside from the differences that I found already, is there any difference between this stateful function component and a stateful class component? Am I incorrect in my above assertion?
To refine this question just a bit, is there anything a Class Component can do that a Function Component with Hooks can't do?
Before The Hooks:
There was a clear separation between Stateful and Stateless
Components.
You use write Classes when you want your component to have some
state, and you use the Function components when you think your
component won’t require any state.
After Hooks:
With the introduction of Hooks, we can create stateful components without using classes.
We can use functions to create stateful components.
Helpful Articles
Article 1
Article 2
As Sung M. Kim said there are 3 life-cycle hooks that is not implemented yet in react hooks.
getDerivedStateFromProps
As mentioned in the docs, getDerivedStateFromProps exists for
only one purpose. It enables a component to update its internal state
as the result of changes in props.
You can achieve the same using useEffect & useState hooks.
useEffect accept as a second parameter an array of dependent variables to that will cause the useEffect to rerun, so you can do the following:
const [state1, changeState1] = useState(props.prop1);
useEffect(() => {
changeState1(props.prop1)
}, [props.prop1]);
componentDidCatch
getDerivedStateFromError
This hooks catch errors in the children tree except the following (docs):
Event handlers (learn more) Asynchronous code (e.g. setTimeout or
requestAnimationFrame callbacks) Server side rendering Errors thrown
in the error boundary itself (rather than its children)
There are a lot of differences between a function and a class, and they show up in the syntax. Furthermore, lifecycle methods in component classes are different than hooks in component functions. But the bottom line is that you aren’t missing any functionality by using function components. In fact function components with hooks are now the default way to create react components. Lots more here:
https://reactjs.org/docs/hooks-intro.html
It is my understanding that the entire React Functional Component gets re-run when re-render is needed or there are any state updates, so how to properly manage the state inside these functions? Is it important to keep it empty of any members like event handlers that you wouldn't want to be re-created every time the function gets re-run?
Is there some sort of best practice for writing optimized functional components?
React Memo is something you might be looking for.
React.memo(...) is a new feature introduced in React v16.6. It works
similiar to React.PureComponent, it helps control functional
components re-renders. React.memo(...) is to functional components
what React.PureComponent is to class components. How do we use
React.memo(…)?
It is very simple. Let’s say we have a functional component, like this:
const Funcomponent = ()=> {
return (
<div>
Hiya!! I am a Funtional component
</div>
)
}
We simply pass the FuncComponent as argument to React.memo function:
const Funcomponent = ()=> {
return (
<div>
Hiya!! I am a Funtional component
</div>
)
}
const MemodFuncComponent = React.memo(FunComponent)
React.memo returned a purified component MemodFuncComponent. This component is what we will render in our JSX markup. Whenever the props and state changes in the component, React will check if the prev state and props and the next props and state are equal if not equal the functional component will re-render if they are equal the functional component will not re-render.
As for second question, yes it's true. You should avoid defining the function inside the render function or in case of functional components, avoid defining inside the function, it will cause unwanted calling of those functions and can result in unwanted behavior as well as cause it to be created every time the component re-renders.
The same goes for adding in-line callback functions for event handlers. They should be defined outside the render function.
As how I get it, You want to know how to manage or improve your react performance right? You are right every Component in react gets re-rendered when there are any state changes in this component or in the parent component (if there is).
So there is a tool (Chrome extension) that helps you finds out which part of the application get re-rendered whenever you make an action React developer tool.
I'm just new to React Hooks, and playaround with it.
Just wondering if there any solutions that I could use useEffect to fetch data several times after componentDidMount.
Normally we use useEffect to fetch data based on some props change by passing them.
useEffect(()=> {
fetchApisomefunction()=>{}
},
[]); // normally do this for componentDidMount
How can I fetch data again after that?
UPDATE
callback function could solve this.
Assuming that you are not using Redux or Context API,
so component A and B are not communicating to each other directly.
On the other hand, there will be a parent component which joins those two components.
As you've said, component B will post the data, and that should change parent's state.
Since react child component is being re-rendered whenever its parent component's state or props change, component A will also be re-rendered.
So all you have to do is to use useEffect without second parameter [].
Actually it is not the question of using Hooks, but the question of react component structure.
Keep in mind that the two child components should not directly communicate to each other.