Custom react hook with useeffect, cant use in non-component function - javascript

I made a custom react hook, which has a useEffect and, for now, returns a set of different states. It's a hook for axios, and the gist of it is this:
export default function useAxios({ url, data = {}, method = "GET"} ) {
var [loading, setLoading] = useState(true)
var [data, setData] = useState(null)
useEffect(function() {
(async function() {
// do axios request and set loading and data states
})()
return () => // cleanup function that cancels axios request
}, [])
return {
loading,
data
}
}
Now, in a simple component I can easily use this custom hook - but my question is: What if I want to use my hook inside an event handler, say:
export default MyComponent() {
function handleSubmit(e) {
var { data } = useAxios({
url: "/my-end-point",
data: {
testInput: e.target.testInput.value
}
})
}
return (
<form onSubmit={handleSubmit}>
<input type="text" name="testInput" />
<button type="submit">Submit</button>
</form>
)
}
Problem is my useAxios hook has a useEffect, and so I cannot use it inside a non-component function, i.e. handleSubmit. So what is the work around? Is there even one? Thanks in advance.

As to React's
Only Call Hooks from React Functions, you should always:
✅ Call Hooks from React function components.
✅ Call Hooks from custom Hooks.
Fail to satisfy these two rules leads to unexpected render result out of React.
With those rules in mind, you should return a submitHanlder from react hook instead of just passing the hook function into another component as a callback function.
I might guess that your intention is to trigger the axios request on the submit event. If so, it is possible to achieve that without passing whole hook into event handler.
First of all, as the rules say, you have to make sure your hook got called in every render. So the MyComponent can be rewrite in the below way:
export default function MyComponent() {
var startRequest = useAxios({url: "/my-end-point"}) //<---- useAxios now returns the startRequest function, and will always be called on every render
return (
<form onSubmit={(e) => {
e.preventDefault()
startRequest({testInput: e.target.testInput.value}) // <----- call your startRequest here in the submit hanlder
.then(data => {
//process your data here
})
}}>
<input type="text" name="testInput" />
<button type="submit">Submit</button>
</form>
)
}
Please note that now the hook returns a function startRequest which you can put in your handler, and trigger that handler any time appropriated.
And rearrange your hook's code like below:
export function useAxios({ url, method = "GET"} ) {
var [loading, setLoading] = useState(true)
// <------ no setData here
var startRequest = async function(body = {}) { // <------ Move your input here
// do axios request and set loading and data states
setLoading(true)
await data = axios.post(body)
setLoading(false)
return data // <------- return data as promise
}
var cancelRequest = () => // cleanup function that cancels axios request
useEffect(function() {
return cancelRequest
}, []) // useEffect only helps your cancel request on unmounted.
return startRequest
}
The useEffect now only helps you cleanup axios request without the need to start one, since firing a request should be an event handler's job.
And since the data return by axios is in a promise, you don't need to explicitly setData to store your response data so I removed the line of useState(null).

I would take a look at popular libraries like SWR (useSWR) and apollo-client (useQuery). They're approach is something like this when making get requests
const MyComponent = () => {
const [shouldSkip, setShouldSkip] = useState(true);
const queryResult = useQuery('my-url', {skip: shouldSkip});
const handleSubmit = () => {
setShouldSkip(false);
// this will cause the component to rerender, and skip will now be false
}
}
When making post requests, its something like this:
const MyComponent = () => {
//useMutation returns a callable function whenever you want
const callFunction = useMutation('my-url');
const handleSubmit = () => {
await callFunction()
}
}
You can also take a look at axios-specific hooks like https://github.com/simoneb/axios-hooks, another common pattern they use is to include a refetch function as a result of the hook, that can be called at anytime (like in an event handler)

The point of the hook is not to make the request for you, the point of the hook is to communicate the internal state of stuff (the axios request, in your case) to the component, so that you can render stuff based around that state (like loading states, or the data).
In your case, you can change the value of the query based on the component state, and have the hook return the data to the component based on its parameters. Something like this:
const useAxios = ({ query }) => {
var [loading, setLoading] = useState(true)
var [data, setData] = useState(null)
useEffect(function () {
(async function () {
setLoading(true)
// do axios request and set loading and data states
const request = await axios.get('endpoint', { query })
setData(request.data)
setLoading(false)
})()
return () => { }// cleanup function that cancels axios request
}, [])
return {
loading,
data
}
}
const Component = () => {
const [query, setQuery] = useState('')
const { loading, data } = useAxios({ query });
const submitHandler = (event) => { setQuery(event.target.testInput.value) }
return (
<>
<form onSubmit={submitHandler}>
<input name="testInput" />
<input type="submit" />
</form>
{loading && (
<>a spinner</>
)}
{data && (
<DataRenderer data={data} />
)}
</>
)
}

Related

React Hook for a POST call onClick

I have a button, onClick of that button I want to make a POST call with some data user has filled in an input field, stored in state, and then redirect the user to another page.
My current code looks like this, but I get an error:
React Hook "usePost" is called in function "onAccept" which is neither a React function component or a custom React Hook function
And the code doesn't work. I have created my own hook for POST calls.
What might a way to make the desired functionality work?
What I'm after is the ability to make a POST call and redirect.
Simplified example:
// my function
const onAccept = () => {
const { data, loading, error } = usePost(
"MY_URL",
{ DATA: MY_DATA }
);
if (data && !error) {
navigate(`/`);
}
};
// return
<button onClick={() => onAccept()}
Yes, You are calling usePost hook inside of onAccept function. You should follow react hook rule.
To solve your problem, you can do like that:
your custom hook file:
export const usePost = () => {
const [status, setStatus] = useState()
const handlePost = useCallback(async (url, data) => {
// your api request logic in here, bellow only show example
try {
const {data, status} = await apiCall(url, data)
if (data && status === 200) navigate(`/`)
} catch (error) {
console.log(error)
}
}, [])
return { handlePost }
// to return status to component, you can use bellow.
// return { status, handlePost }
}
then your component:
const YourComponent: React.FC = () => {
const { handlePost } = usePost()
// To get status: const { status, handlePost } = usePost()
// your other hooks in here
// Check status
useEffect(() => {
if (status === 200) {
// whatever you want to do
}
}, [status])
return (
<>
// Your component UI here
...
<button onClick={() => handlePost(url, data)}>
</>
)
}
You should call your custom hooks(for example: usePost) at the top level of component, not nested function body as like as you were doing in your code (onAccept function body).
I can suggest you do the following.
At first, you should create fetch function which will be returned from usePost hook.
example.
export const usePost = () => {
const [loading, setLoading] = useState(false)
const [data, setData] = useState([])
const fetch = () => {
setStatus(loading)
apiRequest({
url: 'my_url',
method: 'GET',
}).then(response => {
setStatus(false)
setData(response.data.data)
}).catch(e => {
setStatus(false)
})
}
return {
status,
data,
fetch
}
After all, you can call this hook in your component. It will return fetch function. You should call fetch inside onAccept.
Example.
const { data, loading, fetch } = usePost()
const onAccept = () => {
fetch()
}
// return
<button onClick={() => onAccept()}
PS. if you need you can return errors from usePost hook, as well.
First, call you hook from React Function. Read the docs: https://reactjs.org/docs/hooks-rules.html#only-call-hooks-from-react-functions.
Second, you should have some sort of load method in your usePost hook, e.g.: const { load } = usePost(...), in order to make POST request on click.
So your handler will look like:
const onAccept = () => {
load();
// the following block move somewhere before you render the component or better use useEffect hook for that
// if (data && !error) {
// navigate(`/`);
// }
};
I hope this will help.

Displayed data does not update

I am using a function to fetch some data and display the data returned. The problem: The data does not display.
function Profile() {
const profileUser = getData(userId)
return (
<div>
<p>{profileUser?.name}</p>
</div>
)
}
The getData is an asynchronous function returning fetching data from firebase while using await and returning an object.
larz answer is good, but you may get a warning/error about useEffect being async. You aren't supposed to have an asyncronous useEffect method. There is a workaround though.
You need to define an async function inside of the useEffect hook that calls your async function. Then use that data to set the state. You need the state since that is what makes it reactive.
function Profile() {
const [profileUser, setProfileUser] = useState({});
useEffect(() => {
const fetchUserProfile = async () => {
const user = await getData()
setProfileUser(user);
}
fetchUserProfile()
}, []);
return (
<div>
<p>{profileUser?.name}</p>
</div>
)
}
Importantly, dont await your fetchUserProfile call, since again, the useEffect method is not async.
You'll probably want to store profileUser in state and then use useEffect to fetch that data when the component mounts
function Profile() {
const [profileUser, setProfileUser] = useState();
useEffect(async () => {
const user = await getData(userId);
setProfileUser(user);
}, []);
return (
<div>
<p>{profileUser?.name}</p>
</div>
)
}

Attempting to access data after fetching with custom hook not working

I had a basic useFetch hook implementation that defined a fetchData function which would setData to some JSON if successful, then I would called it on useEffect with no dependencies and the hook returned the stateful data value. I found that this was not ideal, because I wanted to fetch things dynamically on events.
So Instead, I changed the useFetch hook to simply return the fetchData function reference along with the data, and no longer call fetchData inside the hook.
const useFetch = () => {
const [data, setData] = useState([]);
const fetchData = async (url) => {
try {
const response = await fetch(url);
if (response.ok) {
const jsonData = await response.json();
setData(jsonData);
} else {
throw new Error(response.status);
}
} catch (err) {
console.error(err);
}
};
return { fetchData, data };
};
This however introduced problems where I use this hook. I've never used this pattern before so I don't really know what I'm doing, but I'm unable to do stuff with the data value after calling the fetch function. Here's basically how I'm using the hook in another functional component:
const [displayedItems, setDisplayedItems] = useState([]);
const { fetchData, data } = useFetch();
useEffect(() => {
fetchData(urlGoesHere);
}, []);
useEffect(() => {
setDisplayedItems(data);
console.log(displayedItems);
}, [data]);
This is ugly, and it doesn't work. I tried putting them all in one useEffect, but that also doesn't work. Sometimes, when I live reload in CRA, I can see data being logged, but typically when my page loads, data just stays undefined. So I basically created another problem by changing useFetch from actually using the fetch function (which has the downside of not being able to be called in my regular functions and event callbacks), and now I can't seem to even render anything.
I'm pretty new to React and async stuff so I'd appreciate a response that takes that into consideration. If there's a much better pattern for the kind of thing I'm trying to do, I'd love to hear it, but I'd like to keep it in vanilla react land, so no libraries, etc. Again, the reason I'm returning a reference to the fetch function is because I want to be able to use it in callbacks and stuff.
Thanks all!
Edit: It sort of works if I check for the truthiness of data in the second useEffect, but anyhow, can this implementation be better?
useEffect(() => {
fetchData(urlGoesHere);
}, []);
useEffect(() => {
if (data) {
setDisplayedItems(data);
console.log(displayedItems);
}
}, [data]);
Does this mean I have to use 2 whole useEffects every time I want to fetch something on load?
You can return more properties than just the data from the hook in order to help you make an informed choice about what and when to render. A common pattern in many simple useFetch hooks like the one you've asked about is to return data, error, and isLoading, so that you can declaratively render the UI you intend to based on a combination of those states, still eagerly fetching the data after the component first renders.
If you need more control over when the data is fetched (e.g. you mentioned in reaction to an "event"), just use the hook in a child component, and conditionally render that child component based on your "event". Below is a typical example of a simplistic useFetch hook (which you can see working in the code snippet):
Here's a link to just the hook in the TypeScript Playground, which you can use to access and copy the transpiled JavaScript if you can't or don't want to use TypeScript.
<div id="root"></div>
<script src="https://unpkg.com/react#17.0.2/umd/react.development.js"></script><script src="https://unpkg.com/react-dom#17.0.2/umd/react-dom.development.js"></script><script src="https://unpkg.com/#babel/standalone#7.16.4/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script>
<script type="text/babel" data-type="module" data-presets="tsx,react">
/**
* The following line is here because this Stack Overflow snippet uses the
* UMD module for React. In your code, you'd use the commented `import` lines
* below it.
*/
const {useEffect, useState} = React;
// import ReactDOM from 'react-dom';
// import {useEffect, useState} from 'react';
// import type {ReactElement} from 'react';
type FetchData<T> = {
data: T | undefined;
error: Error | undefined;
isLoading: boolean;
};
function useFetch <T = unknown>(url: string): FetchData<T> {
const [data, setData] = useState<T | undefined>();
const [error, setError] = useState<Error | undefined>();
const [isLoading, setIsLoading] = useState<boolean>(false);
useEffect(() => {
const ac = new AbortController();
const fetchData = async () => {
setIsLoading(true);
try {
const response = await fetch(url, {signal: ac.signal});
if (!response.ok) throw new Error(String(response.status));
const result = await response.json() as T;
setData(result);
setError(undefined);
}
catch (ex: unknown) {
setError(ex instanceof Error ? ex : new Error(String(ex)));
}
setIsLoading(false);
};
fetchData();
return () => ac.abort();
}, [url, setData, setError, setIsLoading]);
return {data, error, isLoading};
}
type User = { username: string };
function Example (): ReactElement {
const url = 'https://jsonplaceholder.typicode.com/users';
const {data, error, isLoading} = useFetch<User[]>(url);
return (
<div>
<h1>Users</h1>
{
isLoading
? (<div>Loading users...</div>)
: null
}
{
error
? (<div>There was an error loading the data ({error.message})</div>)
: null
}
{
data
? (
<ul>
{data.map(({username}, index) => (
<li key={`${index}-${username}`}>{username}</li>
))}
</ul>
)
: null
}
</div>
);
}
ReactDOM.render(<Example />, document.getElementById('root'));
</script>

Using React Javascript (Form-Onsubmit & calling API not working properly)

i am a bit puzzled with the logic when reading the below code, although the code is working but not exactly as i would like it to behave.
3 queries i have if some one can please clarify.
1- As i understand useEffect is used to invoke the function after render, but in the below code, once the form is sumbitted (onSubmit={credentialVerify}) it will call the credentialVerify() function as below, so i dont think we need useEffect here, but still the code doesnt call the API unless i use the useEffect statement.
2- Also doesnt wait for me to enter my credentails first and as soon as i go to the Signin page it will fetch the API’s (when using useEffect ) and shows the result in the windows, but i try to design in a way that when i click button then it will fetch the API
3- when in the form onsubmit call the credentialVerify function, i have console.log(e) but it is showing as undefined, but as i understand onsubmit will call the function and through the event argument by default.
Below is the snippet of my code.
Any help Appreciated.
import React, { useState, useEffect } from "react";
import "../App.css";
import { Link } from "react-router-dom";
function Signin() {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const updateName = (e) => {
setName(e.target.value);
};
const updatePassword = (e) => {
setPassword(e.target.value);
};
const [items, setItems] = useState([]);
useEffect(() => { //Point-1 useEffect- API not call atall without this statement
credentialVerify();
}, []);
const credentialVerify = async (e) => {
console.log(e); //Point-3 this is coming as undefined
const data1 = await fetch("http://localhost:5000/api/customers");
const incomingdata = await data1.json();
console.log(data1);
console.log(incomingdata);
console.log(name, password);
setItems(incomingdata);
};
return (
<div>
<div>
{
<form className="formstyle" onSubmit={credentialVerify}>
<input
type="text"
placeholder="Username"
name="username"
value={name}
onChange={updateName}
/>
<input
type="text"
placeholder="Password"
name="password"
value={password}
onChange={updatePassword}
/>
<button type="submit">Submit</button>
</form>
}
</div>
<div>
{items.map((entry) => {
let key = entry.email;
let valuefirst = entry.firstName;
let valuelast = entry.created_at;
return (
<p key={key}>
{key}: {valuefirst}bb {valuelast}
</p>
);
})}
</div>
</div>
);
}
export default Signin;
For your first question, you are correct - it doesn't make sense to call credentialVerify when your component renders for the first time since that seems to be the handler for when your form gets submitted. Unless you're fetching data prior to displaying your form, you can drop the useEffect hook entirely.
This is also takes care of your second question because the hook will run once when your component renders for the first time, which is indicated by the empty array [] used as a dependency array of the useEffect hook. This is equivalent to componentDidMount in a class-based component, but again, it doesn't make sense to call credentialVerify at this point.
As for your third question, you should probably do something like the following:
const credentialVerify = event => {
event.preventDefault();
(async () => {
const data = await fetch("http://localhost:5000/api/customers")
.then(res => res.json());
.catch(e => e);
console.log(incomingData);
// ...
})();
}
Since you're passing an asynchronous function as your event handler, you might have issues accessing the SyntheticEvent object due to the reasons stated in React docs:
The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.
reactjs.org/docs/events.html#event-pooling
Your final component should look like the following:
function Signin() {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const [items, setItems] = useState([]);
const updateName = e => {
setName(e.target.value);
};
const updatePassword = e => {
setPassword(e.target.value);
};
const credentialVerify = event => {
event.preventDefault();
(async () => {
const incomingdata = await fetch("http://localhost:5000/api/customers")
.then(res => res.json())
.catch(e => e);
console.log(incomingdata);
console.log(name, password);
setItems(incomingdata);
})();
};
return (
<div>...</div>
);
}

React Hooks - Making an Ajax request

I have just began playing around with React hooks and am wondering how an AJAX request should look?
I have tried many attempts, but am unable to get it to work, and also don't really know the best way to implement it. Below is my latest attempt:
import React, { useState, useEffect } from 'react';
const App = () => {
const URL = 'http://api.com';
const [data, setData] = useState({});
useEffect(() => {
const resp = fetch(URL).then(res => {
console.log(res)
});
});
return (
<div>
// display content here
</div>
)
}
You could create a custom hook called useFetch that will implement the useEffect hook.
If you pass an empty array as the second argument to the useEffect hook will trigger the request on componentDidMount. By passing the url in the array this will trigger this code anytime the url updates.
Here is a demo in code sandbox.
See code below.
import React, { useState, useEffect } from 'react';
const useFetch = (url) => {
const [data, setData] = useState(null);
useEffect(() => {
async function fetchData() {
const response = await fetch(url);
const json = await response.json();
setData(json);
}
fetchData();
}, [url]);
return data;
};
const App = () => {
const URL = 'http://www.example.json';
const result = useFetch(URL);
return (
<div>
{JSON.stringify(result)}
</div>
);
}
Works just fine... Here you go:
import React, { useState, useEffect } from 'react';
const useFetch = url => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const fetchUser = async () => {
const response = await fetch(url);
const data = await response.json();
const [user] = data.results;
setData(user);
setLoading(false);
};
useEffect(() => {
fetchUser();
}, []);
return { data, loading };
};
const App = () => {
const { data, loading } = useFetch('https://api.randomuser.me/');
return (
<div className="App">
{loading ? (
<div>Loading...</div>
) : (
<React.Fragment>
<div className="name">
{data.name.first} {data.name.last}
</div>
<img className="cropper" src={data.picture.large} alt="avatar" />
</React.Fragment>
)}
</div>
);
};
Live Demo:
Edit
Updated based on version change (thanks #mgol for bringing it to
my attention in the comments).
Great answers so far, but I'll add a custom hook for when you want to trigger a request, because you can do that too.
function useTriggerableEndpoint(fn) {
const [res, setRes] = useState({ data: null, error: null, loading: null });
const [req, setReq] = useState();
useEffect(
async () => {
if (!req) return;
try {
setRes({ data: null, error: null, loading: true });
const { data } = await axios(req);
setRes({ data, error: null, loading: false });
} catch (error) {
setRes({ data: null, error, loading: false });
}
},
[req]
);
return [res, (...args) => setReq(fn(...args))];
}
You can create a function using this hook for a specific API method like so if you wish, but be aware that this abstraction isn't strictly required and can be quite dangerous (a loose function with a hook is not a good idea in case it is used outside of the context of a React component function).
const todosApi = "https://jsonplaceholder.typicode.com/todos";
function postTodoEndpoint() {
return useTriggerableEndpoint(data => ({
url: todosApi,
method: "POST",
data
}));
}
Finally, from within your function component
const [newTodo, postNewTodo] = postTodoEndpoint();
function createTodo(title, body, userId) {
postNewTodo({
title,
body,
userId
});
}
And then just point createTodo to an onSubmit or onClick handler. newTodo will have your data, loading and error statuses. Sandbox code right here.
use-http is a little react useFetch hook used like: https://use-http.com
import useFetch from 'use-http'
function Todos() {
const [todos, setTodos] = useState([])
const { request, response } = useFetch('https://example.com')
// componentDidMount
useEffect(() => { initializeTodos() }, [])
async function initializeTodos() {
const initialTodos = await request.get('/todos')
if (response.ok) setTodos(initialTodos)
}
async function addTodo() {
const newTodo = await request.post('/todos', {
title: 'no way',
})
if (response.ok) setTodos([...todos, newTodo])
}
return (
<>
<button onClick={addTodo}>Add Todo</button>
{request.error && 'Error!'}
{request.loading && 'Loading...'}
{todos.map(todo => (
<div key={todo.id}>{todo.title}</div>
)}
</>
)
}
or, if you don't want to manage the state yourself, you can do
function Todos() {
// the dependency array at the end means `onMount` (GET by default)
const { loading, error, data } = useFetch('/todos', [])
return (
<>
{error && 'Error!'}
{loading && 'Loading...'}
{data && data.map(todo => (
<div key={todo.id}>{todo.title}</div>
)}
</>
)
}
Live Demo
I'd recommend you to use react-request-hook as it covers a lot of use cases (multiple request at same time, cancelable requests on unmounting and managed request states). It is written in typescript, so you can take advantage of this if your project uses typescript as well, and if it doesn't, depending on your IDE you might see the type hints, and the library also provides some helpers to allow you to safely type the payload that you expect as result from a request.
It's well tested (100% code coverage) and you might use it simple as that:
function UserProfile(props) {
const [user, getUser] = useResource((id) => {
url: `/user/${id}`,
method: 'GET'
})
useEffect(() => getUser(props.userId), []);
if (user.isLoading) return <Spinner />;
return (
<User
name={user.data.name}
age={user.data.age}
email={user.data.email}
>
)
}
image example
Author disclaimer: We've been using this implementation in production. There's a bunch of hooks to deal with promises but there are also edge cases not being covered or not enough test implemented. react-request-hook is battle tested even before its official release. Its main goal is to be well tested and safe to use as we're dealing with one of the most critical aspects of our apps.
Traditionally, you would write the Ajax call in the componentDidMount lifecycle of class components and use setState to display the returned data when the request has returned.
With hooks, you would use useEffect and passing in an empty array as the second argument to make the callback run once on mount of the component.
Here's an example which fetches a random user profile from an API and renders the name.
function AjaxExample() {
const [user, setUser] = React.useState(null);
React.useEffect(() => {
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
setUser(data.results[0]);
});
}, []); // Pass empty array to only run once on mount.
return <div>
{user ? user.name.first : 'Loading...'}
</div>;
}
ReactDOM.render(<AjaxExample/>, document.getElementById('app'));
<script src="https://unpkg.com/react#16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
I find many wrong usages of useEffect in the answers above.
An async function shouldn't be passed into useEffect.
Let's see the signature of useEffect:
useEffect(didUpdate, inputs);
You can do side effects in didUpdate function, and return a dispose function. The dispose function is very important, you can use that function to cancel a request, clear a timer etc.
Any async function will return a promise, but not a function, so the dispose function actually takes no effects.
So pass in an async function absolutely can handle your side effects, but is an anti-pattern of Hooks API.
Here's something which I think will work:
import React, { useState, useEffect } from 'react';
const App = () => {
const URL = 'http://api.com';
const [data, setData] = useState({})
useEffect(function () {
const getData = async () => {
const resp = await fetch(URL);
const data = await resp.json();
setData(data);
}
getData();
}, []);
return (
<div>
{ data.something ? data.something : 'still loading' }
</div>
)
}
There are couple of important bits:
The function that you pass to useEffect acts as a componentDidMount which means that it may be executed many times. That's why we are adding an empty array as a second argument, which means "This effect has no dependencies, so run it only once".
Your App component still renders something even tho the data is not here yet. So you have to handle the case where the data is not loaded but the component is rendered. There's no change in that by the way. We are doing that even now.

Categories

Resources