According to react, we can call hooks from React Functions and not from Regular Javascript functions.
But what is the difference between both of them ?
From this post it seems like there is no difference and it is just different way of writing.
Please provide an example to make the difference more clear.
React functions are Javascript functions, with some special rules around them.
React functions:
Follow React component naming convention, i.e. they must be Capitalized
Take a single props object argument
Return valid JSX
React functions are NEVER invoked. A reference to them is passed or they are referenced as JSX
and that's about it.
const MyComponent = (props) => <div>{props.greeting}</div>;
Usage:
<MyComponent greeting="Hello World!" />
and never MyComponent({ greeting: "Hello World!" });
This is because the React framework takes this component reference and converts it to a regular old Javascript function and manages calling this function for you. React manages the component lifecycle.
Contrary to the other answer, plain Javascript functions can return JSX. See Rendering Elements. You can assign a JSX literal to a variable, or call a Javascript function that returns a JSX literal.
Example:
const getGreeting = (name) => <div>Hello, {name}!</div>;
const MyComponent = (props) => <div>{getGreeting(props.name)}</div>;
Usage:
<MyComponent name="Drew" /> // --> <div>Hello, Drew!</div>
Similarly, React hooks are also just Javascript functions, but again with special rules applied to them. You can read about these Rules of Hooks.
React hooks follow a naming convention of using a use- prefix
Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions.
Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions.
Can be called in custom React hooks
These are just rules decided on by the React team to make working with and using React hooks manageable and work within React component lifecycle and keep your sanity.
Related
here is my code
function Label({title}){
return <h1>{title}</h1>
}
function useLabel({title}){
return <h1> {title}</h1>
}
function Diff(){
return <div>
<Label title='this is component'/>
{useLabel({title:'this is custom hook'})}
</div>
}
in the code, I have defined the component Label and the custom hook useLabel. they do exactly the same job except that are called using different syntax.
my questions are:
other than calling syntax, what's is the difference between custom
hooks and Components?
can I always use custom hooks instead of
component?
custom hook useLabel
You've given it a name that's conventionally for hooks, but I recommend you don't call it a custom hook as that may cause confusion. Custom hook typically refers to a function that calls one or more of the built in hooks provided by react, such as useState, or useEffect. Because it does this, it brings along the requirement that it needs to follow the rules of hooks.
For example, the following is a custom hook that gets and returns the window width:
const useWindowWidth = () => {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
}
}, [])
return width;
}
What you've written is a helper function, but it doesn't have to follow the rules of hooks, since it never calls hooks. A helper function that returns a react element can occasionally be useful if you have to do the same thing multiple times, but it's basically no different than just writing a longer Diff component. As far as react knows, it's the same as writing the <h1> in the body of Diff.
So your question boils down to: when should i use one component or multiple components.
Sometimes, that decision will be made for performance reasons. If it's all one component, then it all needs to rerender as a group. But if it's split into separate components, then potentially only a subset of them need to rerender.
Other times, the decision is more about how to make the code understandable to us puny humans. Breaking up components at sensible boundaries can let you mentally group related code together, and then ignore it when you don't need to know the details.
Custom hooks are primarily for the abstraction of stateful logic and state manipulation, so that you can write the hook once and use it in multiple places, or without having to worry about implementation details.
While a custom hook can technically return anything, it's pretty strange for it to return a JSX element, because a component could do the same thing less confusingly. One should want to use a custom hook when wanting to return something other than a JSX element while still working within React's framework, for example:
const isOnline = useFriendStatus(props.friend.id);
can I always use custom hooks instead of component?
It'd technically be possible, but it'd be really confusing. Best to always use components when you're returning JSX.
I'm trying to wrap my head around custom hooks. I understand normal hooks which is just fine, but my question is, when writing a custom hook, what is the difference between that and a normal function? I mean why not call it a normal function instead of calling it something like use*
I believe no one has answered your question exactly. I'm still also understanding the benefits and purpose of having this extra feature called hooks, but I can still share my understanding.
React Hooks are JS functions with the power of react, it means that you can add some logic that you could also add into a normal JS function, but also you will be able to use the native hooks like useState, useEffect, etc, to power up that logic, to add it state, or add it side effects, memoization or more.
So I believe hooks are a really good thing to manage the logic of the components in a isolated way.
So, you could have a foo.component.js (UI), a useFoo.js(logic), where useFoo will contain maybe many js functions and one hook to manage that functions and return what it's supposed.
This is an amazing video about react hooks, fully recommended
https://youtu.be/J-g9ZJha8FE
There are some differences and problems that make us use react custom hooks:
First of all, if you use normal functions, with every re-render of the component, this function will be created again and it causes the lack of performance. you may think that it can be fixed by using useCallBack and make react not to create a new function every time it re-renders but it is not the main problem that we are going to solve.
The main problem as the react document has discussed with a brief example of tracking online friends, is avoiding copy-pasting the same logic in different functional components which they need to be stateful too.
If we use normal functions inside a component and use useCallBack to avoid creating a new function every time, we did not solve the problem because in every component we should also copy this logic so this did not solve the problem.
The other solution is to make a function outside the functional component to handle this logic, but there is a big problem: in a normal function outside of the component, we don't have access to states because as we mentioned, this implemented logic is stateful and we have access to states only in react components.
So what is the solution here? yes, Custom React Hooks!
It is a stateful function that uses other react built-in hooks (e.g. useState, useCallback etc.) that can wrap around the stateful logic that you wanted to gather in one place and avoid copy and pasting the same logic in multiple components.
With this approach, you can put your logic outside of the component in another function while you are getting the benefit of stateful functionalities of react.
I hope that this answer may solve your problem and resolve your ambiguity.
From the React docs:
A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks. [...] Its name should always start with "use" so that you can tell at a glance that the rules of Hooks apply to it.
So why define custom Hooks with a special "use" naming prefix?
1.) It tells consumers, that these functions are intended to be used with React and obey to an implicit contract (above mentioned rules).
2.) You can have tooling support which checks and enforces these rules. For example, eslint-plugin-react-hooks utilizes a heuristic that assumes, a function starting with "use" prefix and a capital letter after it is a Hook.
React Hooks (custom or non-custom) should start with the use prefix. As well as, as per the React Documentation:
1) Hooks should be called from the React code only not from the Regular JS functions. Hence, Hooks' scope is limited to the React code world and has more power to do a lot with React code. Rather than JS, regular functions could be used across application but as react code guidelines keep the code more aligned to react syntax.
2) In the class-based components, the Hooks won't work but regular functions will.
3) In the regular JS functions, you can't access useState, useEffect, useContext etc. but in react custom hooks I can.
A custom hook depends on one more other hooks. By design React hooks are meant to be used from a component's render method. You will get a warning if you try to use a hook anywhere else. Custom hooks follow the same convention as built-in hooks because they have to be used in the same fashion. The use prefix is just a convention to identify hook functions which are usually call at the very top of a component render method.
You can name your hook function anything you want but as I mentioned, you will get a warning from React if used outside of a render method.
You can call it whatever and it will still work fine. The only advantage is that if you use the “useName” convention, React will check for error whether it correctly follows the rules of hooks. It just makes your task slightly easier.
As other users have stated custom hooks or hooks, in general, are used where we have to do anything related to react component while other util functions are not tied to react state and won't work is areas where react state logic is in place.
An example of custom hooks be useCustomNavigation which could a list of navigator function like navigateToHome, navigateToCheckout etc. So when you to route to homepage from different parts of code, we just use this hook. Also any logic/feature like analytics, and side effects could be part of navigateToHome function.
An example of Util function could be anything like capitalize which does not has to do anything with react or react component. You cannot create a util function called navigator and add useNavigation.
As I see it, custom hooks have their own specific purpose and have their own characteristics and approach.
What I mean is that in certain cases we would want to create a custom hook and not a function.
For example, if you have a need to store some data in the Localstorage you would want to create a custom hook for that and call it "useLocalStorage" and if you want to create a component, let's say a page form, you would want to write a function component.
Difference being that our hook is not a component and shows nothing on our UI.
It is simply a logical operation.
The reason I see them as different other than the "logical" example above is that our custom hooks are unique in a way of allowing the usage of other custom hook related hooks. For example, the "useDebugValue" which can only work in a custom hook.
What is weird to me is the way React differentiates a function from a custom hook, which I think is the main cause of the confusion.
It "checks" your function name and if it starts with "use" then it's a custom hook. What I think would have been a better option is to change the "const" declaration to a "hook" declaration or give it a unique type.
TL;DR, custom hooks are the logic and will allow the usage of hooks like "useDebugValue" and our functions are mostly UI related.
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
I am wondering, if classes are just syntax sugar for prototypes, and es6 enhances functional coding, can we write reactJS code purely functionally(and without missing out on lifecycle methods)?
[edit]
Think of the most complex react app, can that be written purely functionally - and would it make sense to do that?
EDIT 2019 May:
React Hooks is here: https://reactjs.org/docs/hooks-reference.html
ES6 classes are syntactic sugar for functions and (with some exceptions) it's possible to rewrite them as functions, this is what transpilers like Babel and TypeScript do.
Since component class inherits from React.Component, it needs to prototypically inherit from it. React.Component doesn't have static properties, so a component doesn't need to inherit them.
This component
class App extends React.Component {
state = { name: 'foo' };
componentDidMount() {
this.setState({ name: 'bar'});
}
render() {
return <p>{this.state.name}</p>;
}
}
becomes
function App(props) {
React.Component.call(this, props);
this.state = { name: 'foo' };
}
App.prototype = Object.create(React.Component.prototype);
App.prototype.constructor = App;
App.prototype.componentDidMount = function () {
this.setState({ name: 'bar'});
};
App.prototype.render = function () {
return React.createElement('p', null, this.state.name);
};
This is what now-deprecated React.createClass originally did, create-react-class helper serves this purpose.
if classes are just syntax sugar for prototypes, and es6 enhances functional coding, can we write reactJS code purely functionally(and without missing out on lifecycle methods)?
We can, but functional component isn't the same thing as a component written with desugared JavaScript class. Functional component is specific React term that refers to stateless functional component. Stateless components don't have a state and lifecycle hooks. It's impossible, or at least impractical, to write real React application with stateless components alone.
Think of the most complex react app, can that be written purely functionally - and would it make sense to do that?
Deliberate avoidance of ES6 class syntax doesn't make sense in general because the lack of syntactic sugar results in verbose and unexpressive code without any benefits. A regular React application still needs to use build step and Babel to transpile JSX syntax because desugared JSX is a hierarchy of verbose React.createElement calls. It is practical only if few React components are used in non-React ES5 application that doesn't need build step to be introduced.
However, this may be possible with third-party libraries, e.g. recompose. It's intended to be used with functional components, e.g. lifecycle helper allows to attach lifecycle hooks to them. Of course, it uses component class internally to do that.
you can use stateless component
This article explain
https://hackernoon.com/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc
example: for stateless component
import React from ‘react’;
const HelloWorld = ({name}) => (
<div>{`Hi ${name}`}</div>
);
export default HelloWorld;
NOTE :
my example lacks lifecycle methods implemented by #estus,so if you don't need those lifecycle methods than you can use below code
Yes you can
import React from ‘react’;
function MyComponent(){
return <div>Hello</div>
}
export default MyComponent;
Live Example
No this is not a way of doing stuff. React gives us two types of components. We use them for a particular purpose.Not everything could be written in stateless components (functions). Stateless components are usually presentation components which only render jsx and have no local state. We can't write methods in stateless components and here comes the Stateful components (class based) where we manage our own state and write methods into it. Further it gives us more control to render our child components. So everything in react follows a pattern and it allows to utilize the power of one way binding.
I am trying to understand #trepidacious's scalajs-react wrapper for this HOC react component.
1a) Why is the type of the wrapped component here ReactComponentC[P,_,_,_] ?
1b) Why is the return type of the component ReactComponentU_ ?
def wrap[P](wrappedComponent: ReactComponentC[P,_,_,_]): Props => P => ReactComponentU_ = {
2) Why is the factory function passed to SortableElement here ?
val componentFactoryFunction = js.Dynamic.global.SortableElement(wrappedComponent.factory) ?
Does not SortableElement take a Component ?
3) Why are the wrapped props passed like this ?
"v" -> wrappedProps.asInstanceOf[js.Any]
What is the reasoning behind this line ?
Where is that magical v is coming from ? Is it from scalajs-react or from react-sortable-hoc ?
4) What is the reasoning behind this wrapper ? If I want to write a wrapper for another HOC component, what should be the general recepie for that ?
There are quite a lot of parts here, but I've put together some links working from the lowest level to the highest while covering the questions.
The first and most important definitions are of React Components and React Elements. This page has an in-depth explanation - I recommend completely skipping the "Managing the Instances" section since it muddies the waters by describing a traditional UI model while using terms differently to the way they are used in React. In summary my understanding is that:
A React Component is a general concept that can be implemented in multiple ways. However it is implemented, it is essentially a function from props (and optionally state) to page contents - a renderer.
A React Element is a description of page contents, representing a particular rendering of a Component.
React components and props docs describe the two ways of defining a React component, the first one is a function from props to a react element, this is the one we're interested in. The React.createFactory docs then confirm that we can pass such a function to createFactory. As far as I can tell this exists in order to adapt from the multiple ways of defining a React Component (by subclassing React.Component or React.PureComponent, by using React.createClass, or by a function from Props to ReactElement) to a way of rendering props to a ReactElement. We can see something about this by looking at this gist introducing React.createFactory in React 0.12 - essentially they wanted to introduce some abstraction between the class used to define a React Component and the eventual function from props to React Elements that is used when rendering, rather than just letting the class render props directly.
Next we have a minor wrinkle - React.createFactory is flagged as legacy in the docs. Luckily this isn't a major issue, again as far as I can tell React.createFactory(type) just produces a function f(props) that is identical to React.createElement(type, props) - we are just fixing the type argument in React.createElement. I've tested this in the react-sortable-hoc wrapper, and we can use createElement instead of createFactory:
val componentFunction = js.Dynamic.global.SortableContainer(wrappedComponent.factory)
(props) => (wrappedProps) => {
val p = props.toJS
p.updateDynamic("v")(wrappedProps.asInstanceOf[js.Any])
React.asInstanceOf[js.Dynamic].createElement(componentFunction, p).asInstanceOf[ReactComponentU_]
}
We're now nearly at question 2). If we look at the source for SortableElement we can see that the sortableElement function accepts a WrappedComponent argument - this is used to create another React Component, via the "subclass React.Component" approach. In the render function of this class, we can see that WrappedComponent is used as a React Component, so we know that it is indeed a component, even without a static type :) This means that WrappedComponent needs to be something accepted by React.createElement, since this is what a JSX component use desugars to.
Therefore we know that we need to pass to the sortableElement function something that is usable as a React Component in javascript React.createElement function. Looking at the scalajs-react types doc we can see that ReactComponentC looks like a good bet - it constructs components, presumably from props. Looking at the source for this we can see that we have two promising looking values - reactClass and factory. At this point I realise that the code is probably using the wrong one - I've tried replacing .factory with .reactClass and this still works, but makes much more sense since we have the comment to tell us that it gives Output of [[React.createClass()]], which is one of the options for a valid React Component. I suspect that factory also works by essentially wrapping up the provided component in createFactory twice, since the output of createFactory is also usable as its input... I think given this correction we've answered question 2 :) This also pretty much answers question 1a) - ReactComponentC is the scala trait that gets us the .reactClass val we need for a scala-defined React Component. We only care about the type of props it uses (since we have to provide them), hence the P. Since scala IS typed we know that this is what we get from building a scala React Component in the normal way (at least for components I've tried).
On question 1b), I found the type ReactComponentU_ from code like the ReactCssTransitionGroup facade in scalajs-react Addons and the scalajs-react-components notes on interop, which shows wrapping of a non-HOC component. Looking at the type itself we can see that it extends ReactElement, which makes sense - this is the expected result of rendering a React Component. In our wrap function in the SortableElement and SortableContainer facades we are producing (eventually) another function from props to ReactElement, just one that jumps through a few hoops to get there with the HOC approach. I'm not sure why ReactComponentU_ is used instead of just ReactElement, I think this is to do with tracking the state of components through the type, but the code still compiles if I return ReactElement, which is odd.
Question 3) is much easier - scalajs-react works with Props that can be Ints, Longs etc. but in Javascript these are not objects. To make every scalajs component's props be an object, scalajs-react wraps them in an object like {"v": props}, and then unwraps again when they are used. When we wrap a Scala React Component using the HOC, we need to get that wrapped component's props to it somehow. The component produced by the HOC function (the "wrapping" component, SortableElement or SortableContainer) does this by expecting its own props to already contain the wrapped component's props as fields, and it then just lets these flow through to the wrapped component, for example in SortableElement's render:
<WrappedComponent
ref={ref}
{...omit(this.props, 'collection', 'disabled', 'index')}
/>
this.props is passed through to the wrapped component. Since the wrapped scala component requires a "v" field with the scala props object in it, we need to add this to the wrapper component's props. Luckily this field will then pass through unaltered to be interpreted later by the scala component. You won't see the "v" field since scalajs-react will unwrap it for you.
This does raise a problem when wrapping some other HOCs - for example ReactGridLayout's WidthProvider measures the wrapped component's width and passes it through in the props as {"width": width}, but unfortunately we can't see this from scala. There may well be some workaround for this.
That covers the details and references for the parts of the HOC wrapping, but actually the process is pretty easy (providing you don't want to access props "injected" into the wrapped component):
Make a scala object for the facade to organise the code.
Work out what props are required by the wrapper component. For example in SortableElement this is index, collection and disabled. Make a Props case class with these fields, in the facade object.
Write a 'wrap' function in the facade object. This does the following:
Accepts a wrappedComponent: ReactComponentC[P,_,_,_] and passes it to the javascript HOC function (e.g. SortableElement) to produce a new React Component.
Builds a javascript props object with the wrapper component's props AND the magic "v" field with the wrapped component's props.
Uses javascript React.createElement function to produce a ReactElement that renders the wrapped component, and casts this to ReactComponentU_.
Note that at stage 5 we need to convert from our Scala Props case class (the wrapper component's props) to a plain javascript object that can be understood by the HOC. The wrapped component's props just go straight into the "v" field without conversion, just casting to js.Any.
The code I wrote for SortableElement and SortableContainer splits this up a little so that wrap returns a curried function that accepts the props for the wrapper component and produces another function from the wrapped props to the final React element. This means that you can provide the wrapper props once and then use the resulting function like a normal component in your Scala render code.
I've updated the SortableElement facade with the improvements above, and this is pretty much a minimal example of a HOC facade now. I would imagine other HOCs will look very similar. You could probably abstract some of the code for the purposes of DRY, but actually there's not really a lot there anyway.
Thanks for the questions and for helping work this out - looking back through the process and particularly your question on .factory has left me more confident that this is now working the right way (with the changes described).
I don't have all the answers but my understanding is that the author of scalajs-react uses lots of types to prevent errors during construction of components as well as during the lifecycle of the components once constructed. He uses naming conventions with suffixes and letters to separate the types which make sense but can be daunting at first.
1a) ReactComponentC is a constructor for a component (C as in Constructor).
1b) ReactComponentU_ represents an unmounted native (JavaScript) React component.
3) I think, looking at the scalajs-react source, that yes, "v" is a magic key name. There is (was?) also some notes in the source code to the effect that this is not ideal ;)
There is a plan to simplify scalajs-react's types in a new version.