I am trying to load the data from exchangeratesapi but some how I cannot load the exchangerates's data!!
componentDidMount() {
this.setState({loading: true})
fetch("https://api.exchangeratesapi.io/latest")
.then(response => response.json())
.then(data => {
console.log(data)
this.setState({
loading: false,
currency: data,
})
})
}
render() {
var text = this.state.loading ? "loading..." : this.state.currency.BGN
return (
<div>
<p>{this.state.currency.RON}</p>
</div>
)
}
I have try on of the dumbest way to load the data.
omponentDidMount() {
this.setState({loading: true})
fetch("https://api.exchangeratesapi.io/latest")
.then(response => response.json())
.then(data => {
console.log(data)
this.setState({
loading: false,
currency: data,
bulgaria:data.rates.BGN,
})
})
}
And inside of render
var text = this.state.loading ? "loading..." : this.state.currency.bulgaria
But I believe there got a to be a better way to do this.
You are trying to access the property directly from currency however, it exists in rates.
This is incorrect:
{this.state.currency.RON}
It should be:
{this.state.currency.rates.RON}
Similarly, the variable text you created is not used anywhere. IMHO it should be like this:
render() {
const {loading, currency} = this.state;
console.log(currency); //only for debugging
return (
{ loading? 'Loading...' : (
<div>
<p>{currency.rates.RON}</p>
</div>)
}
)
}
Related
So I am making a ToDo app but so far I can just create a task, or delete it. Right now I am trying to make another feature where I can edit the specific task by clicking the edit button and then it will change the task into an input area where i can edit the task name. Can someone help me with this? How it looks right now is displayed below.
My Code right now is below:
import React, { Component } from 'react';
import axios from "axios";
export default class TaskInput extends Component {
constructor(props) {
super(props)
this.state = {
task: " ",
allTasks: [],
strikeThrough: {textDecoration:""}
}
}
changeHandler = (event) => {
console.log(event.target.value)
this.setState({
task: event.target.value,
})
}
handleStrikethrough = (completed, id) => {
// !completed ? this.setState({strikeThrough:{textDecoration: "line-through"}}) : this.setState({strikeThrough:{textDecoration:""}})
// if (!completed) {
// console.log("not completed", !completed)
// this.setState({strikeThrough:{textDecoration: "line-through"}});
// axios.put("/api/task", {
// completed: !completed
// }, id).then(response => console.log(response))
// } else {
// this.setState({strikeThrough:{textDecoration:""}})
// axios.put("/api/task", {
// completed: !completed
// }, id).then(response => console.log(response))
// }
}
handleDelete = (taskId) => {
axios.delete("/api/task/" + taskId).then(data => {
console.log("You deleted the task with an id of ", data)
})
window.location.reload();
}
handleTaskEdit = () => {
console.log("edit button worked")
}
submitHandler = (event) => {
event.preventDefault() //to prevent page refresh
console.log()
fetch("/api/task", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(this.state),
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err))
this.setState({
task: ""
})
window.location.reload()
}
componentDidMount() {
console.log("component did mount")
const self = this;
axios.get("/api/tasks").then(function (data) {
self.setState({
allTasks: data.data
})
// console.log(self.state.allTasks[0].task)
})
}
render() {
const {strikeThrough, task, allTasks} = this.state; //destructuring the state
return (
<div>
<form onSubmit={this.submitHandler} >
<label style={{ margin: "5px 0px" }}>Create a Task:</label>
<input value={this.state.task} onChange={this.changeHandler} style={{ width: "100%" }}></input>
<input style={{ padding: "5px", marginTop: "5px" }} type="submit"></input>
</form>
<hr></hr>
<br></br>
<ul>
{this.state.allTasks.map(task => (
<li style={strikeThrough} onClick={()=>this.handleStrikethrough(task.completed, task.id)} className="tasks">{task.task}
<button onClick = {() => this.handleDelete(task.id)}>x</button>
<button onClick={this.handleTaskEdit}>edit</button>
</li>
)
)}
</ul>
</div>
)
}
}
You could set task ID on its corresponding Edit button, then when clicking Edit button get the task using ID and sending that task to an edit component.
First of all handleTaskEdit, here you set task name to the task property and set ID of editable task:
handleTaskEdit = id =>
this.setState({ task: this.state.allTasks.find(el => el.id === id).task })
secondly, create two new methods, createTask and updateTask:
createTask = () => {
fetch("/api/task", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({task: this.state.task}),
})
.then(res => res.json())
.then(data => this.setState({
task: '',
allTasks: [...this.state.allTasks, data]}))
.catch(err => console.log(err))
}
updateTask = () => {
fetch("/api/task", {
method: "PATCH",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({task: this.state.task, id: this.state.editableTaskId}),
})
.then(res => res.json())
.then(data => this.setState({
task: '',
editableTaskId: null,
allTasks: this.state.allTasks.map(el =>
el.id === data.id ? data : el)})) // Or take new name and id from state
.catch(err => console.log(err))
}
and finally you need to update submitHandler and handleDelete:
submitHandler = () => {
if (this.state.editableTaskId) {
this.updateTask();
} else {
this.createTask()
}
}
handleDelete = (taskId) => {
axios.delete("/api/task/" + taskId).then(data => {
this.setState({allTasks: this.state.allTasks.filter(el =>
el.id !== data.id
)})
})
}
Here's the approach:
Have a state variable called editTaskID and keep the default value as null. On the edit button set the functionality of handleTaskEdit in such a way that it sets the editTaskID to that particular task ID on which edit button was clicked.
In the map function where you are rendering the list items for tasks, add a condition such as:
{this.state.allTasks.map(task =>
(
<li style={strikeThrough}
onClick={()=>this.handleStrikethrough(task.completed, task.id)}
className="tasks">
{
this.editTaskID
?<input
value={this.state.editTaskName}
/*supposing editTaskName to be state variable that stores
the edit textfield content.*/
onChange={this.changeEditHandler} style={{ width: "80%" }}>
</input>
:task.task
}
<button onClick = {() => this.handleDelete(task.id)}>x</button>
<button onClick={this.handleTaskEdit}>edit</button>
</li>
)
)
}
This will now check the condition whether the editTaskID has been set to null or not while rendering. In case if it is null, all your tasks will come as a plain text else it will come in form of a text box. You can also add the value to the edit task input field with the help of allTasks[editTaskID].
On the handleTaskEdit function of the edit button, make sure to set the allTasks[editTaskID] to the value editTaskName and also to set the state variable editTaskID to null.
Call the necessary backend endpoint to reflect the changes in your database as well.
I hope it helps. Thanks.
I have an app which fetch data from a JSON file. The problem is, it fetches the data from top to bottom. I want it to fetches randomly within the JSON file. How would I achieve this?
This is how I fetch the JSON:
componentDidMount() {
const url = ''
this.setState({ isLoading: true });
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.product,
dataBackup: responseJson.product,
isLoading: false
});
})
.catch((error) => {
console.log(error)
})
}
When you're reading a file there is no way to change the order of content.
However, once the json is parsed, since your product key is an array, you can shuffle this array when you setting the state.
You can use the shuffle function from this answer
How to randomize (shuffle) a JavaScript array?
Alternatively if you're using lodash, there is shuffle function for collections :
https://lodash.com/docs/4.17.14#shuffle
Your final code would be:
// import shuffle function from linked anwser,
// or with lodash :
import { shuffle } from "lodash";
// ...
componentDidMount() {
const url = "";
this.setState({ isLoading: true });
fetch(url)
.then(response => response.json())
.then(responseJson => {
this.setState({
dataSource: shuffle(responseJson.product),
dataBackup: responseJson.product,
isLoading: false
});
})
.catch(error => {
console.log(error);
});
}
I'm getting a list of news through api wordpress and displaying posts.js. Now I want to go to the 1post.js page by clicking on each item and displaying that particular item.
componentDidMount(){
return fetch('URL/wp/api/get_posts')
.then( (response) => response.json() )
.then( (responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.posts,
})
})
.catch((error)=> {
});
} render() { if (this.state.isLoading){ return ( ) } else{ let posts=this.state.dataSource.map((val, key) => { return {val.title} }); return ( {posts} );
To navigate from one component to another, you need to create a navigation container. react-navigation is the official module for navigating between components.
Visit this link to create a stack navigator and then you can use below code to achieve the above said.
async componentDidMount() {
fetch('URL/wp/api/get_posts')
.then(res => res.json())
.then(data => this.setState({posts: data }))
}
renderPostList(){
return this.state.posts.map(post=>(
<TouchableOpacity onPress={this.props.navigation.navigate("NextScreen",{selectedPost:post})}>
<Text>{post.title}</Text>
</TouchableOpacity>
))
}
render() {
return (
<View>
{this.renderPostList()}
</View>
)
}
Hi I need to add a state into my API fetch but struggling to see why it works when the state is an empty string but does not work if there is a string inside the state please view the examples
The idea is the user enters new text in an input which updates the state Search and then updates fetch url so they can search the database
Example Working Code (Notice the state Search is empty)
export default class ThirdScreen extends React.Component {
state = {
search: '',
image: ''
}
componentDidMount() {
this.fetchsa();
}
fetchsa = () => {
const {search} = this.state;
fetch(`https://xxx/search?q=moon&media_type=image`)
.then((response) => response.json())
.then((result) => this.setState({
image: result.collection.items[0].links[0].href
}))
}
Example not working Code
export default class ThirdScreen extends React.Component {
state = {
search: 'moon', //Notice this is not empty and now causes an error
image: ''
}
componentDidMount() {
this.fetchsa();
}
fetchsa = () => {
const {search} = this.state;
fetch(`https://xxx/search?q='${search}'&media_type=image`)
.then((response) => response.json())
.then((result) => this.setState({
image: result.collection.items[0].links[0].href
}))
}
The problem are the single quotes in your fetch URL:
const search = 'moon';
fetch(`https://xxx/search?q='${search}'&media_type=image`)
is NOT the same as
fetch(`https://xxx/search?q=moon&media_type=image`)
The API request goes through for 'moon' instead of moon and no results are found.
However this is ok:
fetch(`https://xxx/search?q=${search}&media_type=image`)
So:
Lose the single quotes around ${search}.
Handle an empty items array when no results are found.
For example:
fetch(`https://xxx/search?q=${search}&media_type=image`)
.then((response) => response.json())
.then((result) => result.collection.items.length > 0 && this.setState({
image: result.collection.items[0].links[0].href
}))
Try this:
export default class ThirdScreen extends React.Component {
state = {
search: 'moon', //Notice this is not empty and now causes an error
image: ''
}
componentDidMount() {
this.fetchsa();
}
fetchsa = () => {
const {search} = this.state;
fetch(`https://xxx/search?q='${search}'&media_type=image`)
.then((response) => response.json())
.then((result) => this.setState({
result.collection && result.collection.items[0] && result.collection.items[0].links[0] ?image: result.collection.items[0].links[0].href:null
}))
}
I have a fetch returning on ComponentDidMount(). Trying to get the response to render on the page.
I have set the state as follows:
this.state = {
loading: true,
file: null,
video: null,
marks: []
};
and my fetch:
componentDidMount() {
return fetch('http://10.0.2.2:8080/marks/createMark')
.then(response => response.json())
.then((data) => {
this.setState({
loading: false,
marks: data.mark
}, () => {
console.log(data.mark);
console.log(this.state.marks);
// const dataMap = data.mark.map((item) => {
// return {
// key: item.id,
// label: item.mark
// };
// });
});
})
.catch(err => console.log(err));
}
Now my render inside of the return:
const { marks } = this.state;
<FlatList
data={marks}
renderItem={({ item }) => <Text>{item.mark}</Text>}
keyExtractor={(item, index) => index}
/>
Do I have to map the data then try to render it??
OUTPUT OF console.log(this.state.marks):
{ _id: '5b61e47a55a0000aa980fab1', mark: 'ItHe', __v: 0 }
The mark is a pseudorandom string that can contain letters and numbers created on the backend
As this.state.marks is an object. First, you need to convert it to this form [{}]. You can do the following changes to make it work.
fetch('http://10.0.2.2:8080/marks/createMark')
.then(response => response.json())
.then((data) => {
let marks = [data.mark]; //Add this line
this.setState({
loading: false,
marks: marks // Change this line
}, () => {
....
Rest of your code
marks is an array but you're not sharing what each object in the array looks like. If it's an array of strings, you're good but if it's an object, you'll need to destructure it and pull out the string you're looking to render.
<Text>{item.mark.someKeyWhoseValueIsAString}</Text