How use async return value from useEffect as default value in useState?
Now that useFetch
returns a value that is available asynchronously, what you need is to update localState when the remoteValue is available, for that you can write an effect
const remoteName = useFetch();
// i want to see the remote value inside my textfield
const [name, setName] = useState(remoteName);
useEffect(
() => {
console.log("inside effect");
setName(remoteName);
},
[remoteName] // run when remoteName changes
);
const onChange = event => {
setName(event.target.value);
};
Working demo
This is exactly same case as setting initial state asynchronously in class component:
state = {};
async componentDidMount() {
const response = await fetch(...);
...
this.setState(...);
}
Asynchronously retrieved state cannot be available during initial render. Function component should use same technique as class component, i.e. conditionally render children that depend on a state:
return name && <div className="App">...</div>;
This way there's no reason for useFetch
to have its own state, it can maintain common state with the component (an example):
const useFetch = () => {
const [value, setValue] = useState("");
useEffect(
async () => {
const response = await fetch("https://httpbin.org/get?foo=bar");
const data = await response.json();
setValue(data.args.foo);
},
[] // executed on component mount
);
return [value, setValue];
};
function App() {
const [name, setName] = useFetch();
const onChange = event => {
setName(event.target.value);
};
return name && (
<div className="App">
<p>local name: {name}</p>
<input onChange={onChange} value={name} />
</div>
);
}