I'm trying to create a delete method in reactJS. My logic is to get the data from the api, use that data in the this.state and call it from the componentDidMount to delete the data.
I can't figure out how to make at the this.state to display the data ID or so I can delete it.
When I click Delete button I get the error of TypeError: Cannot read property 'state' of undefined
Anyone has an idea?
class DeleteForm extends Component {
constructor(props){
super(props);
this.state = {
id: ''
}
}
async componentWillMount() {
const url = 'http://localhost:8080/zoom';
const response = await fetch(url);
const data = await response.json();
console.log(data);
}
componentDidMount() {
axios.delete(`http://localhost:8080/zoom/${this.state.id}`)
.then(res => console.log(res.data));
}
render() {
return(
<button onClick={this.componentDidMount}>Delete</button>
)
}
}
Assuming that you have id in the response. You can do it like this.
class DeleteForm extends Component {
constructor(props){
super(props);
this.state = {
id: ''
}
}
async componentDidMount() {
const url = 'http://localhost:8080/zoom';
const response = await fetch(url);
const data = await response.json();
this.setState({
id: data.id
})
}
delete = () => {
axios.delete(`http://localhost:8080/zoom/${this.state.id}`)
.then(res => console.log(res.data));
}
render() {
return(
{this.state.id && <button onClick={this.delete}>Delete</button>}
)
}
}
Your button will show up only when id is set.
Related
class MyAttendees extends React.Component {
static contextType = AuthContext;
constructor(props){
super(props);
this.state = {
barcodesData: []
}
}
componentDidMount() {
this.fetchBarcodeData()
}
fetchBarcodeData() {
const { currentUser, GetBarcodesByUser } = this.context; // getting current user logged in and a function
const uid = currentUser.uid; // uid of the user
GetBarcodesByUser(uid) // this will return a array of string containing barcodes id
.then( data => this.setState({ barcodesData: data }))
}
// force rerender
forceUpdater() {
this.forceUpdate();
}
render() {
return (
<div>
{
// trying to render the array list
// this is not rerendering even after the barcodes is updated
this.state.barcodesData.map((item) => {
console.log("item: ", item)
return <h1 key={item}>{item}</h1>
})
}
</div>
)
}
}
export default MyAttendees;
const GetBarcodesByUser = async ( uid: string ): string[] => {
const data = await getBarcodesByUser(uid);
return data;
}
export const getBarcodesByUser = async ( uid: string ): string[] => {
const result = [];
const q = query(collection(firestore, "qrcode"), where("uid", "==", uid));
onSnapshot(q, (querySnapshot): string[] => {
querySnapshot.forEach( document => {
result.push( document.id )
})
})
return result;
}
Things that I have tried
at first I was using function approach with useEffect.
I tried to use function to render array.
I tried to use the fetching function inside componentDidMount() function
Tried forceUpdate
Any of the above method is not working
Not 100% that was the entire console.log so my guess is you are mapping the wrong bit. Try changing your state to set like this
.then( response => this.setState({ barcodesData: response.data }))
I want to fetch data that returns successfully after componentDidMount, but before there is an error that singer.data is undefined:
// imports
export default class LookSinger extends Component {
state = {
singer: {}
}
componentDidMount () {
let { singer } = this.props.location.state;
singer = singer.replace(/ /g,"+");
const fetchData = async () => {
try {
const response = await fetch(
`http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=${singer}&api_key=a3c9fd095f275f4139c33345e78741ed&format=json`
);
const data = await response.json();
this.setState({
singer: data
})
} catch (error) {
console.log(error.message);
}
}
fetchData();
}
render() {
let singer = this.state.singer
return(
<div>
{console.log(singer.artist.name)} // gives undefined but after fetching artist.name absolutely exists
</div>
)
}
}
Url is:http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=Ariana+Grande&api_key=a3c9fd095f275f4139c33345e78741ed&format=json
The problem is here:
{console.log(singer.artist.name)}
In the initial render, singer.artist is undefined and if you call singer.artist.name it will throw error. name of undefined.... You just need to wait for data to fetch and update the state.
Try like this
export default class LookSinger extends Component {
state = {
singer: {}
}
componentDidMount () {
let { singer } = this.props.location.state;
singer = singer.replace(/ /g,"+");
const fetchData = async () => {
try {
const response = await fetch(`http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=${singer}&api_key=a3c9fd095f275f4139c33345e78741ed&format=json`);
const data = await response.json();
this.setState({ singer: data })
} catch (error) {
console.log(error.message);
}
}
fetchData();
}
render() {
const { singer } = this.state
if (!singer.artist) { // <-- Check if the data is present or not.
return <div>Loding singer info...</div>
}
return(
<div>
<h1>{singer.artist.name}</h1>
</div>
)
}
}
You do let singer = this.state but there's no this.setState({ singer: ... }) in your code. Instead of this.setState({ data }), try this.setState({ singer: data })
Set you state as below and,
const data = await response.json();
this.setState({
singer: data
})
and you can log it out likes this,
console.log(this.state.singer)
I am working on an API using axios:
constructor(props) {
super(props);
this.state = {
url:[],
title:'anime',
limit:6,
}
this.more_button.bind(this)
}
componentDidMount() {
//limit is on the end of the url
const limit= this.state.limit
axios.get(`http://api.giphy.com/v1/gifs/search?q=sth&api_key=MY_KEY&limit=` + limit)
.then(res => {
const url= res.data.data;
this.setState({ url });
})
}
I want to change limit when i click on a button;
and i do it like this:
more_button=()=>{
this.setState((previousState) => {
return { limit: previousState.limit + 6 };
});
this.componentDidMount();
}
The problem is that i should click that button twice in order to work.
render part:
render(){
return(
<div className="container">
<button
onClick={this.more_button} >
Give me More!
</button>
)
}
}
ComponentDidMount is a lifecycle method. Don't call this function manually,Try below code.
componentDidMount() {
//limit is on the end of the url
this.apiCall();
}
apiCall() {
const limit= this.state.limit
axios.get(`http://api.giphy.com/v1/gifs/search?q=sth&api_key=MY_KEY&limit=` + limit)
.then(res => {
const url= res.data.data;
this.setState({ url });
})
}
more_button = () => {
this.setState((previousState) => {
return { limit: previousState.limit + 6 };
});
this.apiCall();
}
Change your render onClick method like:
onClick={()=>this.more_button}
Finally add extra line in constructor:
constructor(props) {
super(props);
this.state = {
url:[],
title:'anime',
limit:6,
}
this.apiCall = this.apiCall.bind(this);
this.more_button = this.more_button.bind(this);
}
Trying to understand why the component's state is becoming undefined.
Before the async call the console shows this.state.pubsubtopics as [], after the call it becomes undefined
code:
class PubSubTopics extends React.Component{
constructor(props){
super(props);
this.state = {
pubsubtopics: [],
};
}
componentDidMount() {
console.log('after component mounted');
console.log(this.state.pubsubtopics);
this.callBackEndAPI()
.then(res =>
this.setState({pubsubtopics: res.express}))
.catch(err => console.log(err));
console.log('after setting state');
console.log(this.state.pubsubtopics);
}
callBackEndAPI = async () => {
const response = await fetch('/listtopics');
const body = await response.json();
if(response.status !== 200){
throw Error(body.message)
}
return body;
}
handlePrintStateClick = () => {
console.log(this.state.pubsubtopics);
}
render(){
return(
<div>
<ul>
</ul>
<button onClick={this.handlePrintStateClick}>printState</button>
</div>
)
}
}
Logs (last log entry is from clicking the button):
after component mounted
index.js:16 []
index.js:21 after setting state
index.js:22 []
index.js:36 undefined
res.express didn't exist in the server's response, using res.topics solved the problem
I am trying to display a list of user repositories. Through the spread operator attempts to spell the object. However, I do not know if this is a good method, there are no errors in the console, but nothing appears on the screen. This is my code.
class ItemUserDetail extends React.Component {
constructor() {
super();
this.state = {
usersRepos: []
};
}
componentDidMount() {
const { user } = this.props.match.params;
const url = `https://api.github.com/users/${user}/repos`;
fetch(url)
.then(res => res.json())
.then(json => this.setState({ usersRepos: json }));
}
render() {
const Repos = this.state.usersRepos ? { ...this.state.usersRepos } : null;
return (
<div>
<p>{Repos.name}</p>
</div>
);
}
}
export default ItemUserDetail;
Since you are returning an array of repositories, your render method should look like this
render() {
const Repos = this.state.usersRepos ? this.state.usersRepos : null; // you don't need this
const { userRepos } = this.state; // destructure
return (
<div>
{userRepos.map(repo => <p key={repo.id}>{repo.name}</p>)}
</div>
);
}