Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
i'd like to know how can I use and consume this json, showing and updading always the list, please i need this for my work and i am struggling to make it.
HERE THE JSON
It's just like in React. First you should fetch the data(usually componentDidMount() is a good place for that. You need to update your component's state to contain the fetched data. Here is an example using axios, but the same effect can be achieved with fetch API.
class MyComponent extends Component {
state = {
data : []
}
componentDidMount(){
axios.get('myendpoint')
.then(res => this.setState({data : res}))
}
render(){
const { data } = this.state
return(
<FlatList
data={data}
renderItem={({item}) => <Text>{item}</Text>}
/>
)
}
}
With fetch
class MyComponentWithFetch extends Component {
state = {
data : []
}
componentDidMount(){
fetch('myendpoint')
.then(docs => docs.json())
.then(res => this.setState({data : res}))
}
render(){
const { data } = this.state
return(
<FlatList
data={data}
renderItem={({item}) => <Text>{item}</Text>}
/>
)
}
}
ps: Don't forget the keys
Related
So, I've been learning react native lately and I am trying to create an RSS reader.I have managed to Download the RSS data but I am stuck in implementing them into JSX ( Screen). I've been trying using setState method but it didn't work.
I can get the RSS data logged into Console but I can't display them in user through JSX
PS: Comments are just tests that I made
class HomeScreen extends React.Component {
state = {
feed: {},
items: {}
};
RSS() {
return fetch("http://di.ionio.gr/feed/")
.then(response => response.text())
.then(responseData => rssParser.parse(responseData))
.then(rss => {
this.setState(() => ({
//...prevState,
feed: rss
//titles: rss.items,
}));
});
}
render() {
{this.RSS();}
return (
<View style={styles.top}>
<HeaderScreen {...this.props} />
<Text>{this.state.feed.title}</Text>
</View>
);
}
}
I've been using react-native-rss-parser.
I also tried without setState but that also didn't work.
Thanks in advance
With your current setup, you're creating an endless loop. This is because you have a side effect (i.e. network request) in your render function.
When your request returns and you call setState your component is rendered again, which in turn calls the network again with this.RSS(), etc. etc. etc.
To fix this, move the this.RSS() to either your constructor function or better yet to the componentDidMount function.
i.e.
componentDidMount() {
this.RSS();
}
render() {
return (
<View style={styles.top}>
<Text>{this.state.feed.title}</Text>
</View>
);
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm trying to fetch data, get it to state and then modify it
state = {
data: []
}
I have this state with an empty array, then I fetching data from API
constructor(){
super();
this.getItem();
}
getItem(){
this.service
.mergeData()
.then((body) => {
this.setState({
data: body.map(product => product),
})
})
}
And then I am trying to use this data from state:
dataToFilter = this.state.data.map((e) => {
return e;
})
But the problem is dataToFilter is empty because the state is empty
How can I solve this?
Edit: OP asked the below question, so I have updated my StackSnippet to reflect this question.
I need to use data in the state not in the render function but in the component after the componentDidMount. Am I able to do that?
If you want to load data after the component mounts, you can use the componentDidMount life cycle method. You can read more on life cycle methods here and here.
Furthermore, you will need to use an arrow function with getItem() if you are not binding the method inside the constructor..
CodePen showing how to use a class method in the constructor via an arrow function.
CodePen showing how to use a class method without an arrow function, using bind, in the constructor.
Here is how you can use componentDidMount to retrieve API data:
CodePen Mirror
class ApiFetcher extends React.Component {
state = {
apiData: "",
id: 1
};
componentDidMount() {
this.getNextFromApi();
}
getNextFromApi = () => {
fetch(`https://jsonplaceholder.typicode.com/todos/${this.state.id}`)
.then(response => response.json())
.then(json => {
this.setState({
id: this.state.id + 1,
apiData: json
}, () => {
// After you set your state,
// you can use the callback that `setState` provides
this.doSomethingWithData();
});
});
}
doSomethingWithData = () => {
// Here is where you can do something with the data
this.setState({ message: 'Check your console!' });
console.log("I am doing something with the data!", this.state.apiData);
// Do whatever you need to here
}
render() {
return (
<div>
{this.state.message ? <p>{this.state.message}</p> : ""}
<hr /><br /><br />
<h3>Just pretend this does not exist, if you do not want to display data here</h3>
<button onClick={this.getNextFromApi}>Next Result</button>
{this.state.apiData ? (
<pre>{JSON.stringify(this.state.apiData, null, 2)}</pre>
) : (
<p>Unable to get data..</p>
)}
</div>
);
}
}
class App extends React.Component {
render() {
return <ApiFetcher />;
}
}
ReactDOM.render(<App />, document.body);
<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>
I think it's better, you use componentwillupdate method for call dataToFilter.
Or
This code call in render method.
dataToFilter = this.state.data.map((e) => {
return e;})
I am working to build a Pokedex from JSON data in React. I am refactoring this project from one I built in jQuery, so it could be that the jQuery approach is causing me to misunderstand how to approach this problem with proper React thinking. What's tripping me up so far is how to dynamically render multiple child elements based on the JSON I pass from a the parent element (this would be jQuery append).
Here is my App.js code:
class App extends Component {
render() {
return (
<div className="App background">
<div className="content">
<Header />
<TilesContainer pokedexName="national"/>
</div>
</div>
);
}
The TilesContainer essentially receives the name of a Pokedex and makes a call to an API. The individual Pokemon names are stored in an array in the TilesContainer state (this.state.pokemon), as below.
class TilesContainer extends Component {
constructor(props){
super(props);
this.state = {pokemon: []};
this.getPokemon = this.getPokemon.bind(this);
this.tiles = this.tiles.bind(this);
}
getPokemon() {
// set this.state.pokemon to the list
let link = 'https://pokeapi.co/api/v2/pokedex/' + this.props.pokedexName + '/';
fetch(link)
.then(response => response.json())
.then(myJson => {
let list = myJson['pokemon_entries'];
list.forEach(pokemon => {
this.state.pokemon.push(pokemon);
})
})
this.tiles();
}
tiles() {
if (this.state.pokemon.length > 0) {
return (
this.state.pokemon.map(pokemon => {
<Tile number={pokemon.entry_number}/>
})
)
}
}
render(){
this.getPokemon();
return (
<div id="tiles-container"
className="tiles-container">
<h1>TilesContainer Test</h1>
<Tile number={1} />
</div>
)
}
}
export default TilesContainer
Again, the idea is that a Pokemon tile is render for each Pokemon in the Pokedex JSON (which for now I've stored in this.state.pokemon - not sure if this is the best approach). I found an example here on Stack Overflow that uses an additional function (this this case this.tiles() to generate what I think is an array of returns with different child elements). The <Tile number={1} /> is a hardcoded example of how the tile is called.
Currently no dynamically-rendered tiles show up when the code runs. Is this the correct approach. I'd really appreciate any suggestions.
Thanks!
It looks like you're almost there.
First off, never modify state directly. Use this.setState() instead. State in React is updated asynchronously. For your purposes, you should be able to modify getPokemon() like the following. I also removed the this.tiles() call, as it is unnecessary.
getPokemon() {
// set this.state.pokemon to the list
let link = 'https://pokeapi.co/api/v2/pokedex/' + this.props.pokedexName + '/';
fetch(link)
.then(response => response.json())
.then(myJson => {
let list = myJson['pokemon_entries'];
this.setState({
pokemon: list,
});
})
}
A minor correction for tiles(): when using an arrow function and returning something in one line, use parentheses instead of curly braces. When you use curly braces, you have to include a return statement. With parentheses, you do not.
tiles() {
if (this.state.pokemon.length > 0) {
return (
this.state.pokemon.map(pokemon => (
<Tile number={pokemon.entry_number}/>
))
)
}
}
Next, since tiles() returns your dynamic tile components, it needs to be included in what you return in render().
render(){
return (
<div id="tiles-container"
className="tiles-container"
>
<h1>TilesContainer Test</h1>
{this.tiles()}
</div>
)
}
Lastly, I think the call to this.getPokemon() would make more sense in the constructor, rather than in render().
I think your method of getting the json data and storing it in state is fine, by the way. In the future, you may want to look into Redux to manage your state, but it could be overkill for a really small application.
so you are passing the pokedexName from the parent component which is app.js, once you get the props you can call the rest api call on the componentWillMount life cycle.
so on the render since the api call has been initiated it wont have any data thats why we are using a ternary operator to check the array once the api call get finished and we get the data we are setting the data to the pokemon array.
Since the state is updated react will automatically render a re render so the data will appear.
i hope the below code will solve the issue, please let me know :)
// App.js
import React, { Component } from 'react';
import TilesContainer from './components/TileContainer/TilesContainer'
class App extends Component {
render() {
return (
<div>
<TilesContainer pokedexName="national" />
</div>
);
}
}
export default App;
// Tiles container
import React, {Component} from 'react';
import axios from 'axios';
class TilesContainer extends Component{
//state
state ={
pokemon: []
}
// life cycle methods
componentWillMount(){
let link = 'https://pokeapi.co/api/v2/pokedex/' + this.props.pokedexName + '/';
axios.get(link)
.then(res => {
this.setState({
pokemon: res.data["pokemon_entries"]
})
})
}
render(){
let style ={display:"inline"}
return(
<div>
{
this.state.pokemon.length > 0 ?
this.state.pokemon.map(pokemon => {
return(
<div key={pokemon.entry_number}>
<p style={style}>{pokemon.entry_number}</p>
<a href={pokemon.pokemon_species.url}>{pokemon.pokemon_species.name}</a>
</div>
)
})
:
null
}
</div>
)
}
}
export default TilesContainer
I am making a movie application with ReactJS and the TMDb API, I would like to get the movies by genres, and display them in my homepage, for that I created for example a method initHorrorMovies() who:
Performs an axios TDMb API request for movies of a kind
https://developers.themoviedb.org/3/discover/movie-discover
Changes the state horrorMoviesList with new data
The problem is that there are many genres, so I'm going to create as many functions and states as there are genres.
I was thinking of creating a movieList object that would contain the results of the tmdb query for each genre as well as the title of the genre, and then update a movieList state with that object.
Do you have any suggestions for me?
I tried this
class App extends Component {
constructor(props){
super(props);
this.state = {
movieListWithGenre:[],
}
}
componentWillMount() {
this.initGenreMovie();
}
initGenreMovie(){
axios.get(LINK_GENRES).then(function(response){
this.initListMovie(response.data.genres)
}.bind(this));
}
initListMovie(GenreList){
this.setState({ moviesList: this.state.moviesList.push(newMovies)});
GenreList.map((element) => {
axios.get(`${API_END_POINT}discover/movielanguage=en
&with_genres=${element.id}
&include_adult=false&append_to_response=images
&${API_KEY}`).then(function(response){
this.setState({movieListWithGenre:this.state.movieListWithGenre.
push(response.data.results)})
}.bind(this));
})
}
}
Edit
Hello, I allow myself to go back the post because I develop a solution that works, I am able to get the list of films sorted by genres using the TMDB API request.
My solution works but I have a lot of latency when launching the application because I think the procedure is heavy, performance is impaired.
Here is my code, could I have some tips to improve this code? I thank you in advance for answers.
class App extends Component {
constructor(props){
super(props);
this.state = {
defaultgenre:28,
movieListWithGenre:[],
genreList:[],
genreId:[],
genreTitle:[]
}
}
componentDidMount() {
this.initGenreMovie();
}
initGenreMovie(){
axios.get(`${LINK_GENRES}`).then(function(response){
this.initListMoviesWithGenre(response.data.genres)
}.bind(this));
}
initListMoviesWithGenre(genres){
genres.map((genre) => {
axios.get(`${API_END_POINT}${POPULAR_MOVIES_URL}&${API_KEY}`)
.then(function(response){
let movies = response.data.results.slice(0,14);
let titleGenre = genre.name;
let idGenre = genre.id;
this.setState({movieListWithGenre:[...this.state.movieListWithGenre, movies]});
this.setState({genreTitle:[...this.state.genreTitle, titleGenre]});
this.setState({genreId:[...this.state.genreId, idGenre ]});
}.bind(this));
})
}
render(){
const renderVideoListGenre = () => {
if(this.state.movieListWithGenre) {
return this.state.movieListWithGenre.map((element,index) => {
return (
<div className="list-video">
<Caroussel
key={element.name}
idGenre {this.state.genreId[index]}
movieList={element}
titleList={this.state.genreTitle[index]}
/>
</div>
)
})
}
}
return (
<div>
{renderVideoListGenre()}
</div>
)
}
export default App
Once you discovered all the genre ids you want you can begin making axios calls to
https://api.themoviedb.org/<GENRE_ID>/genre/movie/list?api_key=<API_KEY>&language=en-US
You can make a single function for all genres or split them up, but should likely be called in the constructor. Once your axios calls return, you can put the movies data into your state like so:
this.setState({ moviesList: this.state.moviesList.push(newMovies) });
The shape of your movie and moviesList object is up to you and the data returned by the API.
I have a backend Drupal site and react-native app as my frontend. I am doing a graphQL query from the app and was able to display the content/s in console.log. However, my goal is to use a call that query inside render return method and display it in the app but no luck. Notice, I have another REST API call testName and is displaying in the app already. My main concern is how to display the graphQL query in the app.
Below is my actual implementation but removed some lines.
...
import gql from 'graphql-tag';
import ApolloClient from 'apollo-boost';
const client = new ApolloClient({
uri: 'http://192.168.254.105:8080/graphql'
});
client.query({
query: gql`
query {
paragraphQuery {
count
entities {
entityId
...on ParagraphTradingPlatform {
fieldName
fieldAddress
}
}
}
}
`,
})
.then(data => {
console.log('dataQuery', data.data.paragraphQuery.entities) // Successfully display query contents in web console log
})
.catch(error => console.error(error));
const testRow = ({
testName = '', dataQuery // dataQuery im trying to display in the app
}) => (
<View>
<View>
<Text>{testName}</Text> // This is another REST api call.
</View>
<View>
<Text>{dataQuery}</Text>
</View>
</View>
)
testRow.propTypes = {
testName: PropTypes.string
}
class _TestSubscription extends Component {
...
render () {
return (
<View>
<FlatList
data={this.props.testList}
...
renderItem={
({ item }) => (
<testRow
testName={item.field_testNameX[0].value}
dataQuery={this.props.data.data.paragraphQuery.entities.map((dataQuery) => <key={dataQuery.entityId}>{dataQuery})} // Here I want to call the query contents but not sure how to do it
/>
)}
/>
</View>
)
}
}
const mapStateToProps = (state, ownProps) => {
return ({
testList: state.test && state.test.items,
PreferredTest: state.test && state.test.PreferredTest
})
}
...
There are few different things that are wrong there.
Syntax error is because your <key> tag is not properly closed here:
(dataQuery) => <key={dataQuery.entityId}>{dataQuery})
And... there is no <key> element for React Native. You can check at docs Components section what components are supported. Btw there is no such an element for React also.
Requesting data is async. So when you send request in render() this method finishes execution much earlier before data is returned. You just cannot do that way. What can you do instead? You should request data(in this element or its parent or Redux reducer - it does not matter) and after getting results you need to set state with .setState(if it happens inside the component) or .dispatch(if you are using Redux). This will call render() and component will be updated with data retrieved. There is additional question about displaying spinner or using other approach to let user know data is still loading. But it's orthogonal question. Just to let you know.
Even if requesting data was sync somehow(for example reading data from LocalStorage) you must not ever do this in render().This method is called much more frequently that you can expect so making anything heavy here will lead to significant performance degradation.
So having #3 and #4 in mind you should run data loading/fetching in componentDidMount(), componentDidUpdate() or as a part of handling say button click.