How to insert params in the fetch url in React Native? - javascript

My skills in React Native is basic, i want to insert the params id in the url to show the posts according to the category.
export default class PostByCategory extends Component {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.params.Title}`,
});
constructor(props) {
super(props);
this.state = {
isLoading: true,
};
}
componentDidMount() {
return fetch(ConfigApp.URL+'json/data_posts.php?category='`${navigation.state.params.IdCategory}`)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
}, function() {
});
})
.catch((error) => {
console.error(error);
});
}

You have to replace navigation.state.params.IdCategory with this.props.navigation.state.params.IdCategory.
It's not a good practice to manually concat your params to the url. I suggest you look at this question to learn how to properly construct your query string.

componentDidMount() {
return fetch(ConfigApp.URL+'json/data_posts.php?category='+this.props.navigation.state.params.IdCategory)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
}, function() {
});
})
.catch((error) => {
console.error(error);
});
}

Related

Fetching with parameters in Javascript

As a quick summary, im trying to fetch from a URL and do so with 2 parameters.
I have no experience with javascript so i was trying this:
componentDidMount() {
$input = array("team" => {teamName}, "name" => {userPrincipalName});
fetch("http://localhost/openims/json.php?function=getDocuments&input=".urlencode(json_encode($input)))
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
files: result.files
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
This however does not seem to work. So my question would be: how do i succesfully pass the teamName and userPrincipalName from the context to the json_encode.
There is however 1 more problem with my code. I currently have two componentDidMounts, which are both using setState. The problem seems to be that whatever setState happens last, is the one that is being worked with, while the first setState is being completely overwritten. But i do need to do both the context setState AND the fetch to achieve my goal.
Here is my full code to give as clear an image as possible of what im doing:
import React from 'react';
import './App.css';
import * as microsoftTeams from "#microsoft/teams-js";
class Tab extends React.Component {
constructor(props){
super(props)
this.state = {
context: {}
}
}
componentDidMount(){
microsoftTeams.getContext((context, error) => {
this.setState({
context: context
});
});
}
componentDidMount() {
$input = array("team" => {teamName}, "name" => {userPrincipalName});
fetch("http://localhost/openims/json.php?function=getDocuments&input=".urlencode(json_encode($input)))
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
files: result.files
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const { teamName, userPrincipalName } = this.state.context;
const { error, isLoaded, files } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
{files.map(file => (
<li key={file.id}>
{file.name} {file.type}
<span id="user">Team: {teamName}, userPrincipalName: {userPrincipalName }</span>
</li>
))}
</ul>
);
}
}
}
export default Tab;
TL;DR
How do i use setState two times without problems? and how do i work the parameters teamName and userPrincipalName into my fetch?
Thank you!
If I understand correctly, what you need is backticks:
`http://localhost/openims/json.php?function=getDocuments&input=${userPrincipalName}`

Correct way to fetch through array

In the below compoenent, the function is neverending. Can someone tell me what to fix so that in the end the beers array in the state has 5 names?
export default class GetBeers extends React.Component {
constructor() {
super();
this.state = {
beers: [],
didError: false
};
this.getBeerInfo = this.getBeerInfo.bind(this);
}
render() {
return (
...
}
getBeerInfo() {
let beerArr = [1,2,3,4,5];
this.props.beerArr.map(id => {
fetch(`https://api.punkapi.com/v2/beers/${id}`)
.then(res => res.json())
.then(json => {
this.setState(state => {
const beers = state.beers.concat(json[0].name);
return {
beers
};
});
})
.catch(err => {
this.setState({
didError : true
});
});
})
}
}
Well your code should be somethings like this ..
import React from 'react';
export default class GetBeers extends React.Component {
constructor() {
super();
this.state = {
beers: [],
didError: false
};
this.getBeerInfo = this.getBeerInfo.bind(this);
}
render() {
return (
<div>{this.state.beers}</div>
)
}
componentDidMount() {
this.getBeerInfo()
}
getBeerInfo() {
let beerArr = [1,2,3,4,5];
beerArr.map(id => {
fetch(`https://api.punkapi.com/v2/beers/${id}`)
.then(res => res.json())
.then(json => {
this.setState({
//const beers = state.beers.concat(json[0].name);
//return {
//beers
//};
beers: this.state.beers.concat(json[0].name)
});
console.log('well at least this works')
})
.catch(err => {
this.setState({
didError : true
});
});
})
}
}
It is advised that you use the componentDidMount() lifecycle method for the fetch api and add what #atahnksy said.
When you are using setState, you can try this:
this.setState({ beers: [...this.state.beers, json[0].name])
This might fix your problem.
You can improve the render method using a combination of ternary operator(to display appropriate message when it cannot reach the server), format with map and ordered list to get something like this :
render() {
return (
<div><ol>{this.state.beers.length!==0 ? this.state.beers.map((beer)=><li>{beer}</li>) :"Could not retrieve any bears. Try again/ensure you can access the server/networtk"}</ol></div>
)
}

Refactoring using Async and await in React?

Im (very) new to react having come from a Java background. I am trying to refactor some existing code to use Async and await.
The error is coming right before my render function() (highlighted with *****) and am getting a "/src/App.js: Unexpected token, expected "," error and cant for the life of me figure out what is going on. Ive tried messing around with } ) and ; and cant quite track it down. Any help is appreciated.
import React, { Component } from "react";
import { FixedSizeGrid } from "react-window";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
specialties: [],
isLoaded: false,
error: null
};
}
async componentDidMount() {
const response = await fetch (url)
.then(response => response.json())
.then(body => {
const specialties = body.data.specialties;
return specialties;
})
.then(specialties => {
return specialties.map(({ _id, name }) => {
return [_id, name];
})
.then(transformed => {
this.setState({
specialties: transformed,
isLoaded: true,
error: null
});
})
.catch(error => {
this.setState({
specialties: [],
isLoaded: true,
error: error
});
});
}
render() {***********************here
if (this.state.error) {
return <span style={{ color: "red" }}>{this.state.error.message}</span>;
}
if (!this.state.isLoaded) {
return "Loading...";
}
const ITEM_HEIGHT = 35;
return (
<FixedSizeGrid
columnWidth={300}
rowHeight={35}
itemData={this.state.specialties}
height={ITEM_HEIGHT * this.state.specialties.length}
width={600}
itemSize={() => ITEM_HEIGHT}
columnCount={2}
rowCount={this.state.specialties.length}
>
{SpecialtyYielder}
</FixedSizeGrid>
);
}
}
const SpecialtyYielder = ({ columnIndex, rowIndex, data, style }) => {
return (
<div
style={{
...style,
backgroundColor:
(rowIndex + columnIndex) % 2 ? "beige" : "antiquewhite",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
{data[rowIndex][columnIndex]}
</div>
);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
You're missing a bracket and paren:
async componentDidMount() {
const response = await fetch (url)
.then(response => response.json())
.then(body => {
const specialties = body.data.specialties;
return specialties;
})
.then(specialties => {
return specialties.map(({ _id, name }) => {
return [_id, name];
})
}) // missing closing bracket and paren
.then(transformed => {
this.setState({
specialties: transformed,
isLoaded: true,
error: null
});
})
.catch(error => {
this.setState({
specialties: [],
isLoaded: true,
error: error
});
});
}
Async/Await
Basically everywhere you used then, you can just use await instead, but in a way such that you don't need a bunch of callbacks and the logic is like synchronous code:
async componentDidMount() {
try {
const response = await fetch (url)
const body = await response.json()
const specialties = body.data.specialties;
const transformed = specialties.map(({ _id, name }) => {
return [_id, name]
})
this.setState({
specialties: transformed,
isLoaded: true,
error: null
})
}
catch(error) {
this.setState({
specialties: [],
isLoaded: true,
error: error
})
}
}
Looks like you might need a better text editor ;). It's in your componentDidMount. At the very end you're missing a ), to close off your .then block and then another curly brace to close componentDidMount
async componentDidMount() {
const response = await fetch (url)
.then(response => response.json())
.then(body => {
const specialties = body.data.specialties;
return specialties;
})
.then(specialties => {
return specialties.map(({ _id, name }) => {
return [_id, name];
})
.then(transformed => {
this.setState({
specialties: transformed,
isLoaded: true,
error: null
});
})
.catch(error => {
this.setState({
specialties: [],
isLoaded: true,
error: error
});
});
})
}
This addresses your syntax error. The way you phrased the question made it seem like you thought the "resolution" to it was to use async/await. You obviously can still do a refactor. Are you interested in still exploring async/await?
You are missing }) in componentDidMount method:
import React, { Component } from "react";
import { FixedSizeGrid } from "react-window";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
specialties: [],
isLoaded: false,
error: null
};
}
async componentDidMount() {
const response = await fetch (url)
.then(response => response.json())
.then(body => {
const specialties = body.data.specialties;
return specialties;
})
.then(specialties => {
return specialties.map(({ _id, name }) => {
return [_id, name];
})
.then(transformed => {
this.setState({
specialties: transformed,
isLoaded: true,
error: null
});
})
.catch(error => {
this.setState({
specialties: [],
isLoaded: true,
error: error
});
});
})}
render() {
const ITEM_HEIGHT = 35;
return (
<FixedSizeGrid
columnWidth={300}
rowHeight={35}
itemData={this.state.specialties}
height={ITEM_HEIGHT * this.state.specialties.length}
width={600}
itemSize={() => ITEM_HEIGHT}
columnCount={2}
rowCount={this.state.specialties.length}
>
{SpecialtyYielder}
</FixedSizeGrid>
);
}
}
const SpecialtyYielder = ({ columnIndex, rowIndex, data, style }) => {
return (
<div
style={{
...style,
backgroundColor:
(rowIndex + columnIndex) % 2 ? "beige" : "antiquewhite",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
{data[rowIndex][columnIndex]}
</div>
);
};

Fetch the first element from the array with fake api 'myjson.com'

In the 'myjson.com' website, I created a url 'https://api.myjson.com/bins/17qwmf' which returns an array to me. How to get an element with 'id: 1', the first element from the array. I'm trying to do it this way: 'https://api.myjson.com/bins/17qwmf/1' but I'm getting an error.
From the documentation it looks like it can be done: http://myjson.com/api
Code here: stackblitz demo
class Items extends Component {
constructor (props) {
super(props);
this.state = {
items: []
}
}
componentDidMount() {
const id = 1;
axios.get
axios({
url: `https://api.myjson.com/bins/17qwmf/${id}`,
method: "GET"
})
.then(response => {
console.log(response.data);
this.setState({
items: response.data
});
})
.catch(error => {
console.log(error);
})
}
render () {
return (
<div >
</div>
)
}
}
if there is no a router for getting an element by it id, you have to filter got array
class Items extends Component {
constructor (props) {
super(props);
this.state = {
items: []
}
}
componentDidMount() {
const id = 1;
axios.get
axios({
url: `https://api.myjson.com/bins/17qwmf`,
method: "GET"
})
.then(response => {
console.log(response.data);
this.setState({
items: response.data.filter(item => item.id === id)[0] // you will get a first element of got array
});
})
.catch(error => {
console.log(error);
})
}
render () {
return (
<div >
</div>
)
}
}
Please check this `https://api.myjson.com/bins/17qwmf?id=${id} if you want to fetch only element with id that ur passed

ReactJS setState variable is undefined

I am trying to filter an array and set its state with the filtered version of that array. My code looks like this:
class Overview extends Component {
constructor() {
super();
this.state = {
card: []
}
}
deleteItem(id) {
fetch('/api/v1/story/'+id,{
method: 'DELETE',
})
.then(response => response.json())
.then(response => {
if(response['response'] == "success"){
this.setState({
//this is where it says this.state is undefined
card: this.state.card.filter(s => s.storyId !== id)
});
}else{
toastr.warning('dit item is al verwijderd', '', {positionClass: "toast-bottom-right", timeOut: 40000})
}
})
}
componentDidMount() {
fetch('/api/v1/overview')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
card: responseJson
})
})
}
render(){return (
<div className="deleteItem" onClick={deleteItem}>
</div>
)}
What happens here is that the page loads and fills the cards array (which works), the cards then get loaded in the DOM and when u click on an icon it should filter out the removed card from the card array and then set the state to the filtered array.
But whenever i get to this.setstate and try to filter it gives me this error:
app.js:66418 Uncaught (in promise) TypeError: Cannot read property 'card' of undefined
I hope i explained it good enough and that someone can help me with this. Thanks in advance!
Try this.
Also, why you make 2 .then()? Why not just one and use ()=>{and here you can write more than one line}
Edited: If you use arrow functions you don't need to bind the context of THIS
https://medium.com/byte-sized-react/what-is-this-in-react-25c62c31480
If you don't want to use arrow functions, you need to bind the context in the constructor
this.myFunction= this.myFunction.bind(this);
class Overview extends Component {
constructor() {
super();
this.state = {
card: []
}
}
deleteItem=(id)=> {
fetch('/api/v1/story/'+id,{
method: 'DELETE',
})
.then(response => response.json())
.then(response => {
if(response['response'] == "success"){
this.setState({
//this is where it says this.state is undefined
card: this.state.card.filter(s => s.storyId !== id)
});
}else{
toastr.warning('dit item is al verwijderd', '', {positionClass: "toast-bottom-right", timeOut: 40000})
}
})
}
componentDidMount() {
fetch('/api/v1/overview')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
card: responseJson
})
})
}
render(){return (
<div className="deleteItem" onClick={this.deleteItem}>
</div>
)}

Categories