Do you want to request a feature or report a bug?
Question
What is the current behavior?
The SetStateAction returned from useState hook dose not accept a second callback argument. It cannot works like Class Componet's 'setState' method, which receives a callback param, and can perform the callback after this setState action updates;
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:
https://codesandbox.io/s/93mkr1ywpr
What is the expected behavior?
Hopes the SetStateAction function can receive a second callback argument, and can used like 'setState' method callback.
I have read the official note:
// this technically does accept a second argument, but it's already under a deprecation warning // and it's not even released so probably better to not define it.
If instead it's working as intended, how can I perform special action after this SetStateAction called ?
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
16.7.0-alpha.0
Is there a reason you can't useEffect
instead? Generally it's a better solution.
Is there a reason you can't
useEffect
instead? Generally it's a better solution.
Since I don't want to trigger callback action every time after dispatching a SetStateAction. But 'useEffect ' might cause the effect running every time after the state changed.
Use a useRef for setting a flag saying you want the effect to run, or just do the effect directly in the function where you're calling setState, as you shouldn't be doing it in the render phase to begin with.
Since I don't want to trigger callback action every time after dispatching a SetStateAction. But 'useEffect ' might cause the effect running every time after the state changed.
Can you describe a more specific use case please?
@gaearon
Hi, i also faced similar issue where i needed to add a callback for when the state is set, my scenario is this:
I make an api call, after i get the response, i update a context state item, then i take the user to a new page (pushing to history), currently, without the callback, i get a warning that says:
Warning: Can't perform a React state update on an unmounted component.
Basically, i'm running a setState on a component that has been unmounted due to the page change.
Ideally, i would like to update the context (or any callback function from parent component for example), then once that process is done, run the callback that will apply the page change.
This could've been done easily with the setState(state, [callback]).
Please advise, thanks for your time!
I found the solution, we can actually await the set function :+1:
Thanks
@therayess Where is it documented that the set function of useState returns a promise?
It doesn't, you can technically await anything in js, but that doesn't really mean anything in this case, it's not waiting until the state flushes to resolve
You are right, apologies for that, it worked for another reason, is there a way to achieve a state set callback with useState ?
Being able to pass a callback to useState
's returned setState
would allow for greater flexibility. For example, we could implement a dispatch
function that takes a callback to fire off post-reducer-update, like UpdateWithSideEffects
in Reason-React: https://reasonml.github.io/reason-react/docs/en/state-actions-reducer#state-update-through-reducer
ReasonReact.UpdateWithSideEffects(state, self => unit): update the state, **then** trigger a side-effect.
Right now, it's possible to implement a Redux-like architecture with an added "hook" for running effects AFTER the reducer update with the class API, Context, and this.setState's callback param, but to accomplish the same thing with react-hooks means needing to use useRef
or useEffect
+ extra boilerplate (setting & checking flags to control when the effect is allowed to run).
Today, in Redux-land, people use middleware libraries like redux-saga, redux-observable, redux-loop, etc. to be able to declaratively describe async effects via dispatched actions, because Redux doesn't expose an API function for running effects after a reducer update, but it's not difficult to implement this sort of functionality with the class API & setState's callback param. We could do something similar with react hooks if useState
's setState
or useReducer
's dispatch
accepted a thunk param describing a one-time effect we'd like to run.
This one-time, post-update effect feature could be implemented by offering different variations of "dispatch", like how Reason-React has SideEffects
and UpdateWithSideEffects
in addition to NoUpdate
& Update
. Having these separate versions of "dispatch" instead of a single "dispatch" dynamically overloaded with optional params is nice, because it allows us to be more explicit about our intentions & the static types being passed around.
Alternatively, instead of having different variations of dispatch
, some of which allow for this post-update effect hook, imagine a simple effect system with just a single dispatch
function, but where your dispatched actions could contain an extra key called effect
, either at the top-level, or, perhaps, under meta
for FSA users, where the value is a thunk or some other lazy async data structure we want to execute. I've personally implemented this idea using the class API & setState's callback param and found it pretty useful. If there were some way to provide a callback to useReducer
's dispatch
function that had access to the dispatched action, this sort of thing could be implemented in user-land with hooks.
Untested madness that I'd rather not touch...... but it's an idea, and I have no idea if it works. But it typechecks 🤷♀️
import React from 'react'
function useImperativeEffectsFactory(serialized = true) {
const [, internalSetEffect] = React.useState<Promise<void> | undefined>(undefined)
return React.useCallback<(effect: () => Promise<void> | void) => void>(
effect => {
internalSetEffect(current => {
const promise = (async () => {
try {
if (serialized) {
await current
await effect()
} else {
await Promise.all([current, effect()])
}
} finally {
internalSetEffect(current => (current === promise ? undefined : current))
}
})()
return promise
})
},
[internalSetEffect]
)
}
const useImperativeEffect = useImperativeEffectsFactory()
useImperativeEffect(async () => {
// ...
})
@Kovensky I just tried it out, and that code results in a Too many re-renders. React limits the number of renders to prevent an infinite loop.
error. Might be a simple problem, not sure. Haven't tried to debug it yet.
Anyway, I'm not saying that there aren't other ways to implement the same idea with Hooks, but it does seem like a lot of hoops need to be jumped through in order to do the same thing that currently is possible with the class API's setState
just by passing in a function as an extra param.
I think @joshburgess has a good point!
Having the callback would make it easier to express side effects like the way it's done in ReasonReact https://github.com/reasonml/reason-react/blob/de0803fa5784e434e3d9da374ec3e4e8a7653f12/src/ReasonReact.re/#L591
or in React ReComponent https://github.com/philipp-spiess/react-recomponent/blob/6c75e1ce99238af0db3389c25a2ca0cee5fa8207/src/re.js#L96
And would enable isolating state even more from classes or components that us it.
I agree, i'd like a callback option. Or taking it one step further, I'd love to see a promise returned. That's one thing that's always irked me about setState.
For whatever it's worth, it's probably based on what reason-react
did, but purescript-react-basic
also went with this approach.
data StateUpdate props state action
= NoUpdate
| Update state
| SideEffects (Self props state action -> Effect Unit)
| UpdateAndSideEffects state (Self props state action -> Effect Unit)
https://github.com/lumihq/purescript-react-basic/blob/master/src/React/Basic.purs#L165-L169
Just posting an update here for others, as I hadn't seen this before until just now. It looks like they are already aware that people want this and have some ideas about how it might be possible.
See the Missing APIs section here: https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884
Relevant section in a screenshot:
@gaearon I have this use-case which perhaps matches the issue:
const Component = ({ extValue }) => {
const [value, setValue] = useState(extValue)
useEffect(() => {
// Normally, value is changed within this Component.
// However, whenever `extValue` updates, need to reset value to extValue.
// As soon as flushed, run 'onExternalValueUpdate'
setValue(extValue)
.then(onExternalValueUpdate)
}, [extValue] )
// Internal updates won't trigger `onExternalValueUpdate`
return (<Something value={value} setValue={setValue} />)
}
@bebbi Not arguing against a callback option as it would be a simpler solution, but I believe you could accomplish this by tracking extVal's state in the child.
const Parent = props => {
let [extVal, setExtVal] = useState(0);
useEffect(() => {
setTimeout(() => {
setExtVal(prevVal => prevVal + 1);
}, 5000);
}, []);
return <Child extVal={extVal} />;
};
const Child = props => {
let [state, setState] = useState({
val: props.extVal,
extVal: props.extVal
});
useEffect(
() => {
setState({
val: props.extVal,
extVal: props.extVal
});
},
[props.extVal]
);
useEffect(
() => {
// We know state.val is also done setting
console.log(state);
},
[state.extVal]
);
return <div>{state.val}</div>;
};
@bebbi Sorry, it's not clear why you need it. A full codesandbox showing the full use case (including why a parent needs such a callback) would be useful.
Hi @gaearon, following method example comes from render props class component. I'd like to refactor it with react hooks. All of the methods on this class component has a callback when on setState is called. It passes a currently affected state so that the end user could do something if that action takes place.
selectAll = ({
type = DataBrowser.stateChangeTypes.selectAll,
items,
} = {}) => {
this.internalSetState(
{
type,
selectAllCheckboxState: true,
checked: items,
},
() => this.props.onSelectAll(this.getState().checked),
);
};
and here is the internalSetState function
internalSetState = (changes, callback = () => {}) => {
let allChanges;
this.setState(
currentState => {
const combinedState = this.getState(currentState);
return [changes]
.map(c => (typeof c === 'function' ? c(currentState) : c))
.map(c => {
allChanges = this.props.stateReducer(combinedState, c) || {};
return allChanges;
})
.map(({ type: ignoredType, ...onlyChanges }) => onlyChanges)
.map(c => {
return Object.keys(combinedState).reduce((newChanges, stateKey) => {
if (!this.isControlledProp(stateKey)) {
newChanges[stateKey] = c.hasOwnProperty(stateKey)
? c[stateKey]
: combinedState[stateKey];
}
return newChanges;
}, {});
})
.map(c => (Object.keys(c || {}).length ? c : null))[0];
},
() => {
this.props.onStateChange(allChanges, this.state);
callback();
},
);
};
It would be kinda hard to replicate all this on a codesandbox but if nescessary I could produce something?
This is the component that is in the process of refactoring
Thanks
@gaearon Here is a fiddle example of what I was trying to simplify.
Not necessarily recommending this approach as it's possibly an anti-pattern, but for the people wanting this functionality, I suggest something like this as a solution (https://codesandbox.io/s/qq672lp6xq):
const useStateWithPromise = defaultVal => {
let [state, setState] = useState({
value: defaultVal,
resolve: () => {}
});
useEffect(
() => {
state.resolve(state.value);
},
[state]
);
return [
state.value,
updater => {
return new Promise(resolve => {
setState(prevState => {
let nextVal = updater;
if (typeof updater === "function") {
nextVal = updater(prevState.value);
}
return {
value: nextVal,
resolve
};
});
});
}
];
};
const App = props => {
let [state, setState] = useStateWithPromise(0);
const increment = () => {
setState(prevState => prevState + 1).then(window.alert);
};
return (
<div>
<p>{state}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
Here's my solution
import { useState } from 'react'
const useStateWithEffects = (props, onValueChanged) => {
let [value, setValue] = useState(props)
const setState = (newValue) => {
value = newValue
setValue(value)
onValueChanged(value)
}
return [value, setState]
}
export default useStateWithEffects
Usage:
const [value, setValue] = useStateWithEffects(10, async () => console.log('changed') )
So ... are there plans to add a callback-parameter (or even better returning a Promise) within React?
import React from 'react'
/* :: (any, ?Function) -> Array<any> */
export const useState = (initialState, callback = () => { }) => {
const [ state, setState ] = React.useState(initialState)
const totalCalls = React.useRef(0)
React.useEffect(() => {
if (totalCalls.current < 1) {
totalCalls.current += 1
return
}
callback(state)
}, [ state ])
return [ state, setState ]
}
const App = () => {
const onCountChange = count => {
console.log('Count changed', count)
}
const [count, setCount] = useState(10, onCountChange)
return (
<>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count => count + 1)}>+</button>
</>
)
}
@gaearon useEffect()
runs after every render AFAIK. With the callback I needed it to run only when the state changed.
@Tahseenm your solution provides a "global" callback for all setCount() calls. I think some people need a solution where they can provide a custom callback for each and every setCount() call. Which allows greater flexibility
@Tahseenm
useEffect()
runs after every render
Here is a very good explanation for useEffect()
and general hooks logic - by Dan. I think it should be a mandatory pre-read for everyone posting in this thread (including me).
@zenVentzi
useState
with Global + setState
callback/* :: (any, ?Function) -> Array<any> */
const useState = (initialState, callback = () => {}) => {
const [state, setState] = React.useState(initialState);
/** @NOTE: Handle callback to run for every state change */
const totalCalls = React.useRef(0);
React.useEffect(
() => {
if (totalCalls.current < 1) {
totalCalls.current += 1;
return;
}
callback(state);
},
[state]
);
/** @NOTE: Handle setState callback */
const lookup = React.useRef([]);
React.useEffect(
() => {
const entry = lookup.current.find(([stateSet]) => state === stateSet);
if (Array.isArray(entry)) {
const [, callback] = entry;
callback(state);
}
lookup.current = [];
},
[state]
);
const $setState = (nextStateOrGetter, callback) => {
setState(nextStateOrGetter);
if (typeof callback !== "function") {
return;
}
const nextState =
typeof nextStateOrGetter === "function"
? nextStateOrGetter(state)
: nextStateOrGetter;
lookup.current.push([nextState, callback]);
};
return [state, $setState];
};
const App = () => {
const onCountChange = count => {
console.log("Count changed", count);
};
const [count, setCount] = useState(10, onCountChange);
const decrement = () => setCount(count - 1, () => console.log("dec"));
const increment = () => setCount(count + 1, () => console.log("inc"));
return (
<>
<h1>Count: {count}</h1>
<button onClick={decrement}>-</button>
<button onClick={increment}>+</button>
</>
);
};
@bebbi Thanks will check it out. Not sure if we should make it a mandatory pre-read for this thread
Thanks @bebbi, but I think most of us legitimately just need a function to run after a state change so we can do something with the most recent state values. For example, how can I make an API call after updating state and guarantee that its the latest values? Before it was like the following.
this.setState({
name: 'FakeMan',
}, () => somefakeCall(this.state.name))
Currently with useState that is not possible. In this scenario useEffect won't quite work. I don't want to make the API call on the initial render and I might not necessary want to make the call every time the name state changes, I just want to make this call in a very specific instance.
@gaearon
Hi Dan!
Is there a reason you can't
useEffect
instead? Generally it's a better solution.
Can you explain, why it's a better solution?
Also why it is not implemented ? (as for my understanding, it should be just one call at the right moment, when the state is updated. At least we can do it when useEffect is triggered. Typically using a promise, which will be resolved at the right moment). I bet it's related to optimization, and maybe consistency. But what difference it make from handling it in useEffect).
And what do you think about the statement 'having the callback (||promise). Add a lot of flexibility.' ?
Thank you a lot.
UPDATE
For why it's a better solution. What i can understand, is that using multiple useEffec (separate memory cells)t, tracking the changes of the specific variables. Make the separation easy. And so the after update can be handled just there.
Here a pattern to mimic the after update behavior. It's short and clean. (it use promises)
class that help with that
class UpdateHandler {
queue =[];
flash(states) {
while(this.queue.length > 0) {
this.queue.shift()(states);
}
}
wait () {
return new Promise (resolve => {
this.queue.push(resolve);
});
}
}
const update = new UpdateHandler();
in hook
useEffect(() => {
update.flash(settings);
}, [settings])
in some function where we use setState
async function someFunc(value, setState) {
setState(value);
let newState = await update.wait(); // whatever was passed to the flash method
// use it as you like
}
What do you think ?
@bebbi Sorry, it's not clear _why_ you need it. A full codesandbox showing the full use case (including why a parent needs such a callback) would be useful.
https://codesandbox.io/s/objective-pare-42mn4
A callback for setState would be useful in this case because I don't want the calendar field to be set every time the text input field update.
I could use the formatted value to set the calendar field but not sure if there's a better way.
What's wrong with this:
const [increment, setIncrement] = useState(0);
<button onClick={() => setIncrement(increment + 1)}>Num is: {increment}</button>
My solution
This is also work for dispatch
, but state value is not updated yet on callback function.
import React, { useState } from "react";
const CallBackTest = () => {
const [trueFalse, setTrueFalse] = useState(false);
const callBacksetState = async (data, callBackFunc) => {
await setTrueFalse(data);
callBackFunc(data);
};
const func = data => {
alert(data + " " + trueFalse);
};
//pass function func to callBacksetState function
return <button onClick={() => callBacksetState(true, func)}>Click Me!</button>;
};
export default CallBackTest;
Simple solution for deleting element from state array.
import React from 'react';
function DeleteFromArray() {
const [emails, setEmails] = React.useState([]);
const handleDelete = index => {
let tempArr = emails;
tempArr.splice(index, 1);
setEmails([...tempArr]);
};
return <button onClick={() => handleDelete(index)}> Delete </button>;
}
export default DeleteFromArray
@arascan35
import React from 'react';
export const DeleteFromArray = ({ deletionIndex }) => {
const [ emails, setEmails ] = React.useState([]);
const handleDelete = () => {
setEmails((emails) => emails.filter((email, index) => index !== deletionIndex));
};
return <button onClick={handleDelete}>Delete</button>;
};
Thanks @bebbi, but I think most of us legitimately just need a function to run after a state change so we can do something with the most recent state values. For example, how can I make an API call after updating state and guarantee that its the latest values? Before it was like the following.
this.setState({ name: 'FakeMan', }, () => somefakeCall(this.state.name))
Currently with useState that is not possible. In this scenario useEffect won't quite work. I don't want to make the API call on the initial render and I might not necessary want to make the call every time the name state changes, I just want to make this call in a very specific instance.
@jhamPac
Good point. As in below snippet: I want console.log("Fetch")
to be written when state is updated after btn1 is clicked and _not_ when btn2. With useEffect
it will be cumbersome to implement such scenario.
@gaearon
class App extends React.Component {
state = { flag: false };
render() {
return (
<div className="App">
<button
onClick={
(() => {
this.setState(ps => ({ flag: !ps.flag }));
},
() => {
console.log("Fetch");
})
}
>
btn1
</button>
<button
onClick={() => {
this.setState(ps => ({ flag: !ps.flag }));
}}
>
btn2
</button>
</div>
);
}
}
Not necessarily recommending this approach as it's possibly an anti-pattern, but for the people wanting this functionality, I suggest something like this as a solution (https://codesandbox.io/s/qq672lp6xq):
const useStateWithPromise = defaultVal => { let [state, setState] = useState({ value: defaultVal, resolve: () => {} }); useEffect( () => { state.resolve(state.value); }, [state] ); return [ state.value, updater => { return new Promise(resolve => { setState(prevState => { let nextVal = updater; if (typeof updater === "function") { nextVal = updater(prevState.value); } return { value: nextVal, resolve }; }); }); } ]; }; const App = props => { let [state, setState] = useStateWithPromise(0); const increment = () => { setState(prevState => prevState + 1).then(window.alert); }; return ( <div> <p>{state}</p> <button onClick={increment}>Increment</button> </div> ); };
function useStateWithPromise<T>(defaultVal: T) {
let [state, setState] = useState({
value: defaultVal,
resolve: (value: T) => { }
});
useEffect(() => {
state.resolve(state.value);
},
[state]
);
return [
state.value,
(updater: (value: T) => any) => {
return new Promise(resolve => {
setState((prevState) => {
let nextVal = updater;
if (typeof updater === "function") {
nextVal = updater(prevState.value);
}
return {
value: nextVal,
resolve
};
});
});
}
];
};
How do I use generics?
Not necessarily recommending this approach as it's possibly an anti-pattern, but for the people wanting this functionality, I suggest something like this as a solution (https://codesandbox.io/s/qq672lp6xq):
const useStateWithPromise = defaultVal => { let [state, setState] = useState({ value: defaultVal, resolve: () => {} }); useEffect( () => { state.resolve(state.value); }, [state] ); return [ state.value, updater => { return new Promise(resolve => { setState(prevState => { let nextVal = updater; if (typeof updater === "function") { nextVal = updater(prevState.value); } return { value: nextVal, resolve }; }); }); } ]; }; const App = props => { let [state, setState] = useStateWithPromise(0); const increment = () => { setState(prevState => prevState + 1).then(window.alert); }; return ( <div> <p>{state}</p> <button onClick={increment}>Increment</button> </div> ); };
function useStateWithPromise<T>(defaultVal: T) { let [state, setState] = useState({ value: defaultVal, resolve: (value: T) => { } }); useEffect(() => { state.resolve(state.value); }, [state] ); return [ state.value, (updater: (value: T) => any) => { return new Promise(resolve => { setState((prevState) => { let nextVal = updater; if (typeof updater === "function") { nextVal = updater(prevState.value); } return { value: nextVal, resolve }; }); }); } ]; };
How do I use generics?
Good reference
@gaearon our company ran into this issue today attempting to upgrade (to hooks) a library that employed the callback on setState.
After reading this thread we looked through our code for every instance where we were using it.
We concluded that in nearly every case we were simply (and likely incorrectly) using this to ensure the form only submitted once and could not submit again until after an API call was complete.
Our solution to this problem looks similar to the solution @Tahseenm submitted but we gave it a more appropriate name and usage. This might be useful to build right in to react.
The entire solution follows:
import { useState, useEffect, useCallback } from "react"
// React Hook - useAsyncCallbackWithSemaphore
//
// Use this hook to create a callback capable of triggering an async operation
// (such as an api call ) that will only be triggered once.
//
// You will receive in return an array that contains
// - a callback function
//
// name this function anything you want, and pass it to your "onClick"
//
// - a state variable containing the semaphore status
//
// name this variable anything you want, use it to disable inputs and
// signal to the user that their command is received and processing.
//
// Example:
//
// export default (props) => {
// const [userName, setUserName] = useState('')
// const [saveUserName, isSavingUsername] = useAsyncCallbackWithSemaphore(
// async () => {
// try {
// await mockApiCall(userName)
// }
// catch(e) {
// //TODO handle errors
// }
// },
// [userName]
// )
//
// return (
// <div>
// <MockUsernameForm
// value={userName}
// onChange={setUserName}
// disabled={isSavingUsername}
// />
// <button
// onClick={saveUserName}
// disabled={isSavingUsername}
// >
// Save
// </button>
// </div>
// )
// }
//
const useAsyncCallbackWithSemaphore = (callOnceFn, watchingVars) => {
// store the semaphore in state
const [semaphore, setSemaphore] = useState(false)
// use the state system to delay triggering the async function until after
// the UI has had a chance to disable inputs.
//
// also only allow this call to happen on the first try if the user presses
// the button multiple times
useEffect(() => {
//if semaphore > 1 this is a repeat call that should be ignored
if(semaphore === 1) {
// we need to await the async function so that we can remove the
// semphore on completion
(async () => {
await callOnceFn()
// async function complete. Remove semaphore
setSemaphore(false)
})()
}
}, [semaphore]) // this useEffect will only trigger if the semaphore changes
return [
// result[0] = a callback function that can be used in "onClick" or
// other triggers
useCallback(() => {
setSemaphore(semaphore + 1)
}, , [...watchingVars, semaphore]),
// result[1] = a boolean indicating if the semaphore has been triggered
// to be used by rendering components down-stream
(semaphore > 0)
]
}
export default useAsyncCallbackWithSemaphore
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!
type Action<T> = (preState?: T) => T;
type Dispatch<T> = (state: T | Action<T>) => Promise<T>;
function useMyState<T>(initState: T): [T, Dispatch<T>] {
const [state, setState] = useState(initState);
const [{ __state, __resolve }, __setState] = useState<{ __state?: T, __resolve?: (t: T) => void }>({});
const mySetState: Dispatch<T> = (state: T | Action<T>) => {
return new Promise<T>((resolve) => {
if (typeof state === 'function') {
setState((preState: T) => {
const __state = (state as Action<T>)(preState);
__setState({
__state,
__resolve: resolve
});
return __state;
});
} else {
const __state = state;
__setState({
__state,
__resolve: resolve
});
setState(__state);
}
});
};
useEffect(() => {
if (__state && __resolve) {
__resolve(__state);
__setState({});
}
}, [state]);
return [state, mySetState];
}
function App() {
const [state, setState] = useMyState(0);
useEffect(() => {
console.warn('before', state);
setState(1).then((state) => {
console.warn('after', state);
});
}, []);
return (
<div className="App"></div>
);
}
Most helpful comment
Thanks @bebbi, but I think most of us legitimately just need a function to run after a state change so we can do something with the most recent state values. For example, how can I make an API call after updating state and guarantee that its the latest values? Before it was like the following.
this.setState({ name: 'FakeMan', }, () => somefakeCall(this.state.name))
Currently with useState that is not possible. In this scenario useEffect won't quite work. I don't want to make the API call on the initial render and I might not necessary want to make the call every time the name state changes, I just want to make this call in a very specific instance.