I am going to call async function in onclick event in button. But it is not working. Is it possible to call the async function inside button onlick ?
Here is the code.
Filter button
const FilterButton = (props) => {
return (
<div className="p-2 ">
<button className="btn btn-secondary" onClick={props.fetchInvoices}>Filter</button>
</div>
);
};
fetchInvoices async function
fetchInvoices = async () => {
const invoices = await getInvoices(this.currentState.params);
this.props.store.dispatch(UpdateInvoices(invoices));
};
code to pass function to component
<SearchField store = {this.props.store} fetchInvoices={this.fetchInvoices}/>
This is how I call my asyncs inside an onClick:
<Button onClick={async () => {await this.asyncFunc("Example");} }/>
async asyncFunc(text) {
console.log(text);
}
Your async function:
const asyncFunc = async () => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("I am a done promise!"), 3000)
});
let result = await promise
alert(result);
}
Your button component call:
<button onClick={asyncFunc} >I am a button!</button>
Instead, try doing
<button className="btn btn-secondary" onClick={this.handleFetchInvoices}>Filter</button>
handleFetchInvoices(){
this.props.fetchInvoices
}
<button
onClick={(e) => (async () => {
try {
const invoices = await getInvoices(this.currentState.params);
} catch () {
}
})()}
>I am a button!</button>
In general, it is a bad practice to create an 2x functions inside the button with each click. But it works.
Related
The Code below successfully displays record from Atlassian Jira Storage API
//import goes here
const fetchRec = async () => {
const data = await storage.query().where('key', startsWith('Mykeysxxxxx')).getMany();
return data.results;
};
const App = () => {
const [projects] = useState(fetchRec);
return (
<div>
// display or map projects records here
{projects.map(project => (
<div>
<b>Fullname: {project.fullname}</b>
<b>Email: {project.email}</b>
</div>
))}
</div>
);
}
Here is my Issue. I need to refresh the Records when new data is inserted.
So I implemented the code below. when I click on refresh Records button, the new inserted record is not updated
<Button text="Refresh Records" onClick={async () => { await reloadRec(); }} />
async function reloadRec() {
fetchRec().then(projects);
//const [projects] = useState(async () => await fetchRec());
}
Here is the full code efforts so far
// Import goes here
const fetchRec = async () => {
const data = await storage.query().where('key', startsWith('Mykeysxxxxx')).getMany();
return data.results;
};
async function reloadRec() {
fetchRec().then(projects);
//const [projects] = useState(async () => await fetchRec());
}
const App = () => {
const [projects] = useState(fetchRec);
return (
<div>
// display or map projects records here
{projects.map(project => (
<div>
<b>Fullname: {project.fullname}</b>
<b>Email: {project.email}</b>
</div>
))}
<Button text="Refresh Records" onClick={async () => { await reloadRec(); }} />
</div>
);
}
This is the problem:
async function reloadRec() {
fetchRec().then(projects);
//const [projects] = useState(async () => await fetchRec());
}
In the above function, projects is undefined. And even if it was the same variable as defined in the App function, it's not a function that the then clause would invoke.
I think this is closer to what you want and follows the standard practices.
const App = () => {
const [projects, setProjects] = useState([]);
const fetcher = async () => {
const data = await storage.query().where('key', startsWith('Mykeysxxxxx')).getMany();
setProjects(data.results);
};
// do the initial fetch with an effect
useEffect(() => {
fetcher();
}, []);
return (
<div>
// display or map projects records here
{projects.map(project => (
<div>
<b>Fullname: {project.fullname}</b>
<b>Email: {project.email}</b>
</div>
))}
<Button text="Refresh Records" onClick={fetcher} />
</div>
);
}
InOrder to update information on the DOM you should update a state and DOM will show latest information. You bind and setRecord with fetchData function
Extanding
const App = () => {
const [projects,setProjects] = useState([]);
const fetchRecords = async() => {
const data = await /*... your data base query */
// Assuming projects is an array of project
setProjects(data.projects);
}
useEffect(()=>{
fetchRecords();
},[])
return (
<div>
// display or map projects records here
{projects.map(project => (
<div>
<b>Fullname: {project.fullname}</b>
<b>Email: {project.email}</b>
</div>
))}
<Button text="Refresh Records" onClick={fetchRecords} />
</div>
);
}
So at first when Component is mount you will see Projects list and then when you click on reload fetchRecords is again called resulting in state change and will reflect on dom
I'm trying to set components with 3 functionalities. Displaying PokemonList, getting random pokemon and find one by filters. Getting random pokemon works great but since 2 days I'm trying to figure out how to set pokemon list feature correctly
Below full code from this component.
It's render when click PokemonsList button inside separate navigation component and fire handleGetPokemonList function in provider using context.
The problem is that I can't manage rerender components when PokemonList is ready. For now i need to additionally fire forceUpadte() function manually (button onClick = () => forceUpdate())
I tried to use useEffect() in PokemonList component but it didn't work in any way.
I was also sure that after fetching data with fetchData() function I can do .then(changeState of loading) but it didn't work also.
What Am I missing to automatically render data from fetch in provider in PokemonList component? I'm receiving error about no data exist but if I use forceUpdate then everything is ok
Complete repo here: https://github.com/Mankowski92/poke-trainer
handleGetPokemonList function in provider below
const handleGetPokemonList = () => {
setCurrentPokedexOption('pokemonList');
async function fetchData() {
setImgLoaded(false);
let res = await fetch(`${API}?offset=0&limit=6/`);
let response = await res.json();
response.results.forEach((item) => {
const fetchDeeper = async () => {
let res = await fetch(`${item.url}`);
let response = await res.json();
let eachPoke = {
id: response.id,
name: response.name,
artwork: response.sprites.other['officialartwork'].front_default,
stats: response.stats,
};
fetchedPokemons.push(eachPoke);
};
fetchDeeper();
});
setPokemonList(fetchedPokemons);
if (fetchedPokemons) {
return setLoading(false);
}
}
fetchData()
.then((res) => setLoading(res))
.catch((err) => console.log('error', err));
};
PokemonList component below
import React, { useContext, useState, useCallback } from 'react';
import { StyledPokemonListContainer } from './PokemonList.styles';
import { PokemonsContext } from '../../../providers/PokemonsProvider';
const PokemonList = () => {
const ctx = useContext(PokemonsContext);
const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
const { handleSetImgLoaded } = useContext(PokemonsContext);
return (
<>
{ctx.currentPokedexOption === 'pokemonList' ? (
<StyledPokemonListContainer>
{ctx.pokemonList && ctx.pokemonList.length ? (
ctx.pokemonList.map((item, i) => (
<div className="each-pokemon-container" key={i}>
<div className="poke-id">{item.id}</div>
<div className="poke-name">{item.name}</div>
<img className="poke-photo" onLoad={() => handleSetImgLoaded()} src={item ? item.artwork : ''} alt="" />
</div>
))
) : (
<div className="render-info">Hit rerender button</div>
)}
{/* {ctx.pokemonList ? <div>{ctx.pokemonList[0].name}</div> : <div>DUPPSKO</div>} */}
<div className="buttons">
<button onClick={() => console.log('PREVOIUS')}>Previous</button>
<button className="rerender-button" onClick={() => forceUpdate()}>
RERENDER
</button>
<button onClick={() => console.log('NEXT')}>Next</button>
</div>
</StyledPokemonListContainer>
) : null}
</>
);
};
export default PokemonList;
I am currently trying to build a rock-paper-scissor and what I intend to achieve are this logic:
after the start button clicked, a player has 3seconds to pick a weapon, if not, a random weapon will be picked for the player.
The problem:
When I picked a weapon under the 3seconds, it works just fine. But, when I intentionally let the setTimeout triggered, it is not updating the state automatically. I suspected the if conditions are not met, but I don't know why that happen.
Here is the code snippet:
//custom hooks//
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
const weapons= ['rock', 'weapon', 'scissors']
const App = () => {
const [p1Weapon, setp1Weapon] = useState("");
const prevWeapon = usePrevious(p1Weapon);
const getPlayerTimeout = (playerRef, setPlayer, time) => {
setTimeout(() => {
if (playerRef === "") {
setPlayer(weapons[Math.floor(Math.random() * weapons.length)]);
}
}, time);
};
const startGame = () => {
getPlayerTimeout(prevWeapon, setp1Weapon, 3000);
}
return (
...
<div>
<button
className="weaponBtn"
onClick={() => {
setp1Weapon("rock");
}}
>
rock
</button>
<button className="weaponBtn" onClick={() => setp1Weapon("paper")}>
paper
</button>
<button className="weaponBtn" onClick={() => setp1Weapon("scissors")}>
scissor
</button>
<button type="button" onClick={startGame}>
Start!
</button>
</div>
)
Thanks!
if all you want to do is set a state after x time you can do this very easily like this
this.setState({isLoading: true},
()=> {window.setTimeout(()=>{this.setState({isLoading: false})}, 8000)}
);
this should set the value of isLoading to false after 8 seconds.
I hope it helps
I have the following function which I use in two components:
export const removeItem = (id, cb) => {
try {
const remove = async () => {
await axios.delete(`http://localhost:9000/news/${id}`);
cb();
};
remove();
} catch (e) {
console.log(e)
}
}
Im my NewsItemPage component I want to provide props.history.push('/news') as the second argument, but this code would not work:
<button onClick={() => {removeItem(someId, props.history.push('/news')) }}>remove</button>
Any help much appreciated.
You have to put a function around it to be able to use as callback.
like this <button onClick={() => {removeItem(someId, () => {props.history.push('/news')}) }}>remove</button>
i am new to react. please help me.
i am trying the get a value of data outside render.
data.map(
<button onClick = { () => { console.log (data)}}></button>
)
i am getting the value of data here. but
handleClick = () => {
console.log (data) /// not getting the value
}
<button onClick = { this.handleClick}></button>
if i try this.hadleClick , then i am not getting any value. why . thanks,
It's because you are not passing the value to your handleClick function. A couple options:
Bind the function with the params in your onClick:
data.map(
<button onClick = { this.handleClick.bind(this, data) }></button>
)
Pass an anonymous function to your click handler:
data.map(
<button onClick = { () => this.handleClick(data) }></button>
)
And you'll need to update your handleClick function to accept data as a param:
handleClick = data => {
console.log(data);
}
You should be passing the data you want to print to the function like below:
<button onClick = { () => this.handleClick(data) }></button>
(and your handler function should accept it as well)
handleClick = (data) => console.log(data);