import React, { Component } from 'react';
import { render } from 'react-dom';
import Details from './Details';
import './index.css';
class App extends Component {
constructor() {
super();
this.state = {
usersData: [],
error: null,
selectedUser: null,
};
}
handleClick = (id) => {
const selectedUser = this.state.usersData.find(user => user.id === id)
this.setState(() => ({ selectedUser }))
}
findAlbum = (selectedUser, id) => {
fetch(`https://jsonplaceholder.typicode.com/users/${id}/albums`)
.then(response => response.json())
.then(data => {
selectedUser.albums = data;
})
.catch(err => this.setState({ error: err.message }))
}
setAlbum = (id) => {
const selectedUser = this.state.usersData.find(user => user.id === id)
this.findAlbum(selectedUser, id);
}
render() {
this.state.usersData.forEach(user => {
this.setAlbum(user.id)
})
const usersList = this.state.usersData.map(user => {
return <li key={user.id} onClick={() => this.handleClick(user.id)}>{user.name} {user.username} {user.email} {user.albums.size}</li>
})
return (
<>
<div className="UserList">
<h1>Users</h1>
<ul>{usersList}</ul>
</div>
<Details user={this.state.selectedUser} />
</>
);
}
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(data => {
this.setState({ usersData: data })
})
.catch(err => this.setState({ error: err.message }))
}
}
render(<App />, document.getElementById('root'));
When i am doing console.log selecteduser.albums inside findalbum function it is showing the data but when i did it in the li line it shows cant read size of undefined
i need to create a react app which shows list of users and their name username and email corresponding to each user we have albums we need to show album number also but i cant do it
is there any problem with pass by value or pass by reference in JS?
It's very wrong to update the state directly in react. Instead, use setState with a map and change anything related to a substate there. Also a tip, instead of passing the Id in the forEach and finding the user, just pass the user
Related
I'am unable to Select only one Radio Button from this Context API list so that I can do more actions on that specific id.I want to change the name of the selected radio button as I want after selecting specific id.
import React from 'react'
import './Boxes.css'
export default class Boxes extends React.Component {
constructor(props) {
super(props)
this.state = {
users: [],
selectedID: ''
}
this.changeSelectedId = (e, id) => {
if (e.target.checked == true) {
this.setState({ selectedID: id })
console.log(this.state.users)
}
}
}
componentDidMount() {
axios.get('https:jsonplaceholder.typicode.com/users')
.then(response => {
console.log(response.data)
this.setState({ users: response.data })
})
.catch(error => {
console.log('Error .....')
})
}
render() {
const { users, selectedID } = this.state
const selectedRadio = selectedID == users.id
return (
<>
{users.map((item, index) =>
<div className='boxes' key={index}>{<h4>Name:- {item.name}</h4>}
<input type='radio' names='Userradio' checked={selectedRadio}
onChange={(e) => { this.changeSelectedId(e, users.id) }} />
</div>)}
</>
)
}
};
Try this:
export const Boxes = ({}) => {
const [users, setUsers] = useState([]);
const [selectedId, setSelectedId] = useState('');
const changeSelectedId = (e, id) => {
if (e.target.checked) {
setSelectedId(id)
}
}
useEffect(() => {
axios.get('https:jsonplaceholder.typicode.com/users')
.then(response => {
console.log(response.data);
setUsers(response.data);
})
.catch(error => {
console.log('Error .....')
})
}, []);
return (
<>
{users.map((item, index) => (
<div className='boxes' key={index}>
<h4>Name:- {item.name}</h4>
<input
type='radio'
names='Userradio'
checked={item.id === selectedId}
onChange={(e) => changeSelectedId(e, item.id)}
/>
</div>
)}
</>
);
};
So I'm new to React, and having trouble fetching API. I've successfully fetched data object(I've checked it with console.log(), but somehow cannot setState it. Please see the code below. It's my full code.
import React, { Component } from 'react';
import EachCake from './EachCake';
class Cake extends Component {
constructor(props){
super(props);
this.state = {
}
}
componentDidMount() {
this._fetchApiEachCake();
}
_renderEachCake = () => {
return <EachCake
image={this.cake_object.image}
source={this.cake_object.source}
body={this.cake_object.body}
/>
}
_fetchApiEachCake = () => {
return fetch("http://127.0.0.1:8000/api/cake/3")
.then((response) => response.json())
.then(data => console.log(data))
.then(data => this.setState({cake_object : data}))
// .catch((err) => console.log(err))
}
render() {
return (
<div>
{this.state.cake_object ? this._renderEachCake() : "Loading this cake"}
</div>
)
}
}
export default Cake
For some reason, all I get on the screen is "Loading this cake". What do you think is the problem?
import React, { Component } from 'react';
import EachCake from './EachCake';
class Cake extends Component {
constructor(props){
super(props);
this.state = {
// 🔥 state initialization is optional also, useful for default values
}
}
componentDidMount() {
this._fetchApiEachCake();
}
_renderEachCake = () => {
return (
<EachCake
image={this.state.cake_object.image} // 🌟🌟
source={this.state.cake_object.source}
body={this.state.cake_object.body}
/>
)
}
_fetchApiEachCake = () => {
// 🔥 you can also remove return here
return fetch("http://127.0.0.1:8000/api/cake/3")
.then((response) => response.json())
.then(data => console.log(data) || data) // 🌟
.then(data => this.setState({cake_object : data}))
// .catch((err) => console.log(err))
}
render() {
return (
<div>
{this.state.cake_object ? this._renderEachCake() : "Loading this cake"}
</div>
)
}
}
export default Cake
🌟🌟 must be grabbed from the state not directly from this reference.
🌟 console.log doesn't return anything, so you must return data yourself oق combine setState and logging step both in one step e.g.
.then(cake_object => console.log(cake_object) || this.setState({ cake_object }))
The then() method returns a Promise.
if you are trying to check if the data is loaded or not you should use the callback this.setstate({key: value}, () => {//do something})
you can use this to set a flag whether data has been loaded into state or not. and i also think that you should initialize that cake_object to null.
so after that your code would be like:
this.state = {
loaded: false,
cake_object: null
}
_fetchApiEachCake = () => {
return fetch("http://127.0.0.1:8000/api/cake/3")
.then((response) => response.json())
.then(data => console.log(data))
.then(data => this.setState({cake_object : data}, () => {
console.log(this.state.cake_object);
this.setState({loaded: true});
}))
// .catch((err) => console.log(err))
}
render() {
return (
<div>
{this.state.loaded ? this._renderEachCake() : "Loading this cake"}
</div>
)
}
2 changes :
1.
this.state = {
cake_object:null,
}
_fetchApiEachCake = () => {
return fetch("http://127.0.0.1:8000/api/cake/3")
.then((response) => response.json())
.then((data) => {
console.log(data)
this.setState({cake_object : data})
})
// .catch((err) => console.log(err))
}
Hopefully it works!
I have a list that displays user profiles, names, and the last message sent. Pretty much in a way a regular messaging app displays users. What I'm trying to do is have the list update when there's a change from the users being displayed. I tried having it update on render but with resetting states, it goes onto an infinite loop which brought up my read operations to 10k in a matter of seconds. So far I have it update with pull to refresh but I want it to update live. I'm not sure if I would need to use cloud functions (e.g. onCreate) or a timer to not quickly go over my quota limit.
import React, { Component } from "react";
import { View, FlatList } from "react-native";
import { ListItem } from "react-native-elements";
import fireStoreDB from "../database/FirestoreDB";
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
usersInfo: [],
refreshing: false
};
}
componentDidMount() {
this.LoadUsers();
}
LoadUsers = () => {
fireStoreDB
.getAllUsersExceptCurrent()
.then(
users =>
Promise.all(
users.map(
({ id, username, avatar }) =>
fireStoreDB
.getUserLastMessage(fireStoreDB.getUID, id)
.then(message => ({ id, username, avatar, message }))
)
)
)
.then(users => {
this.setState({
usersInfo: users.filter(x => typeof x.avatar !== "undefined"),
refreshing: false
});
});
};
renderItem = ({ item }) => (
<ListItem
onPress={() => {
this.props.navigation.navigate("Chat", {
userTo: item.id,
UserToUsername: item.username,
LoadUsers: this.LoadUsers
});
}}
title={item.username}
subtitle={item.message}
leftAvatar={{ source: { uri: item.avatar } }}
bottomDivider
chevron
/>
);
render() {
return (
<View>
<FlatList
data={this.state.usersInfo}
renderItem={this.renderItem}
keyExtractor={item => item.id}
refreshing={this.state.refreshing}
onRefresh={() => {
this.setState({ refreshing: true });
this.LoadUsers();
}}
/>
</View>
);
}
}
I solved it by doing this.
async componentDidMount() {
await Font.loadAsync({
"open-sans-semi-bold": require("../assets/fonts/OpenSans-SemiBold.ttf"),
Roboto: require("../node_modules/native-base/Fonts/Roboto.ttf"),
Roboto_medium: require("../node_modules/native-base/Fonts/Roboto_medium.ttf"),
...Ionicons.font
});
this.unsubscribeMsg = fireStoreDB.lastMsgListener(this.LoadUsers);
this.unsubscribeUser = fireStoreDB.userProfileListener(this.LoadUsers);
this.setState({ isReady: true });
}
componentWillUnmount() {
this.unsubscribeUser();
this.unsubscribeMsg();
}
lastMsgListener = loadUsersCallback => {
return firebase
.firestore()
.collectionGroup("chats")
.onSnapshot(() => {
loadUsersCallback();
});
};
userProfileListener = loadUsersCallback => {
return firebase
.firestore()
.collection("users")
.onSnapshot(() => {
loadUsersCallback();
});
};
Because I'm new to using axios so I usually have a trouble in using it. Specifically, I'm making a react-infinite-scroll feature now, but when I compare its speed with other site, my post(react-infinite-scroll feature) is gonna be shown slowly a little. Then I'm thinking this problem is caused by 2 reasons
1. I'm not using axios properly
2. There is a thing makes axios speed urgrade, but I'm not using it
Here's my code, please give me some advice to increase my http request speed.
Thank you for reading my question!
class MainPage extends Component {
constructor(props) {
super(props)
axios.get("http://127.0.0.1:8000/api/question")
.then(res => {
this.setState({
AnswerPostMultiList: res.data
})
}
)
.catch(err => {
console.log(err)
})
}
state = {
AnswerPostMultiList : []
}
componentDidMount() {
window.addEventListener("scroll", this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.handleScroll);
}
handleScroll = () => {
console.log("scroll is executing")
const { innerHeight } = window;
const { scrollHeight } = document.body;
const scrollTop =
(document.documentElement && document.documentElement.scrollTop) ||
document.body.scrollTop;
if (scrollHeight - innerHeight - scrollTop < 1000 && !this.props.isLoading["isLoading"]) {
this.props.onIsLoading() #To prevent this code from calling back continuously, change the value of this.props.isLoading["isLoading"] to false
axios.get("http://127.0.0.1:8000/api/question")
.then(res => {
this.setState({
AnswerPostMultiList: this.state.AnswerPostMultiList.concat(res.data)
})
this.props.onIsLoading() #change the value of this.props.isLoading["isLoading"] to true
}
)
.catch(err => {
console.log(err)
})
}
};
render() {
return(
<>
<PageHeader />
<div className="find_members">
{ this.state.AnswerPostMultiList.map((answerpost,index) => {
return <AnswerPostMulti question={answerpost.question_text} q_owner={answerpost.question_owner} answer={answerpost.answer_image} a_owner={answerpost.answer_owner} key={index} />
})
}
</div>
</>
)
}
}
const mapDispatchToProps = (dispatch) => ({
onIsLoading: () => {
dispatch(isLoadingActions.isLoading())
}
})
const mapStateToProps = state => ({
isLoading: state.isLoading
})
export default connect(mapStateToProps, mapDispatchToProps)(MainPage)
The best place to call a axios API calls is at componentDidMount(){}.
The Application loading process will be in this order skeleton->Initial rendering->later componentDidMount method is called. So here your app skeleton will be loaded and after that you can fetch data and use it to your app skeleton.
componentDidMount() {
axios.get("http://127.0.0.1:8000/api/question")
.then(res => {
this.setState({
AnswerPostMultiList: res.data
})
}
)
.catch(err => {
console.log(err)
});
}
I am having difficulties mapping over this object in order to render the data on the API.
Anyone has an idea of what I may be doing wrong?
class HomePage extends Component {
state = {
weatherResults: []
};
componentDidMount() {
let obj;
fetch(`http://api.openweathermap.org/data/2.5/forecast?
id=52490&appid=${API_KEY}&q=new%20york&cnt=2`)
.then(res => res.json())
.then(results => (obj = results))
.then(() => console.log(obj));
this.setState({
weatherResults: this.state.weatherResults
});
}
render() {
return (
<div>
{this.state.weatherResults &&
this.state.weatherResults.map(data => (
<div className="container">
<p>{data.city.name}</p>
</div>
))}
</div>
);
}
}
export default HomePage;
Since the fetch request is asynchronous, you want to use setState when the request has finished to put the response in the component state.
Looking at one of the sample requests of the API it looks like you get an object as response, which has city.name in it. Instead of having weatherResults be an array, you can set it to null initially and access city.name on it when the object has loaded.
Example
class HomePage extends Component {
state = {
weatherResults: null
};
componentDidMount() {
fetch(`http://api.openweathermap.org/data/2.5/forecast?id=52490&appid=${API_KEY}&q=new%20york&cnt=2`)
.then(res => res.json())
.then(results => {
this.setState({
weatherResults: results
});
})
.catch(error => console.error(error));
}
render() {
const { weatherResults } = this.state;
if (weatherResults === null) {
return null;
}
return (
<div>
<div className="container">
<p>{weatherResults.city.name}</p>
</div>
</div>
);
}
}