1

FlatList is not rendering data from state however it is working for the DATA variable. this.state.DATA is an array of objects just like the DATA variable.The DATA variable is just a dummy variable that was given in the reactnative docs. I want to display the contents of this.state.DATA.

import React, { Component } from 'react';
import { Text, View ,FlatList} from 'react-native';
import SectionHeader from '../SectionHeader';
import {TableHeader,TableHeaderText,IssueContainer} from './style';
import {CheckOutlined,InfoCircleOutlined,CaretDownOutlined} from '@ant-design/icons'
const DATA = [
    {
      id: '1',
      title: "No show password eye button in Login form",
    },
    {
      id: '2',
      title: 'Second Item',
    },
    {
      id: '3',
      title: 'Third Item',
    },
  ];
var repos=[],issues=[];
export default class App extends Component {
    state={isLoading:true};
  componentDidMount() {
    fetch('https://api.github.com/orgs/anitab-org/repos')
    .then((response)=>response.json())
    .then((json)=> json.forEach(function(repo,idx){
        repos.push(repo.name);
        fetch('https://api.github.com/repos/anitab-org/'+repo.name+'/issues')
        .then((response)=>response.json())
        .then((json)=>json.forEach(function(issue,idx){
            var flag=false;
            var issue_tmp={
                id:issue.id.toString(),
                url:issue.html_url,
                title:issue.title,
                milestones:issue.milestones,
                comments:issue.comments,
                number:issue.number,
                assignees:issue.assignees,
                labels:[],
            };
            issue.labels.forEach(function(label){
                if(label.name==="First Timers Only")
                    flag=true;
                issue_tmp.labels.push({
                    id:label.id,
                    name:label.name,
                    color:label.color
                })
            })
            if(flag===true && issue_tmp!=null)
                issues.push(issue_tmp)
        }));
    }))
    .then(()=>{
        this.setState({
            repos:repos,
            DATA:issues,
            isLoading:false,
        });
    })
  }
  render() {
    if(this.state.isLoading===true)
        return(<></>)
    else{
        return (
            <View style={{alignItems: 'left',width:'80%'}}>
                <SectionHeader title="SOME COOL FIRST-TIME ISSUES TO WORK ON"/>
                <TableHeader>
                    <TableHeaderText style={{color:'#000',textAlign:'left'}}><InfoCircleOutlined /> 5 Open</TableHeaderText>
                    <Text style={{flex:6,color:'#586069'}}><CheckOutlined /> 45 Closed</Text>
                    <TableHeaderText>Author <CaretDownOutlined /></TableHeaderText>
                    <TableHeaderText>Label <CaretDownOutlined /></TableHeaderText>
                    <TableHeaderText>Milestone <CaretDownOutlined /></TableHeaderText>
                    <TableHeaderText>Assignee <CaretDownOutlined /></TableHeaderText>
                    <TableHeaderText>Sort <CaretDownOutlined /></TableHeaderText>
                </TableHeader>
                <FlatList
                    data={this.state.DATA}
                    renderItem={({item})=>(
                        <IssueContainer key={item.id}><Text>{item.title}</Text></IssueContainer>
                        )}
                    keyExtractor={item => item.id}
                />
            </View>
            );
        }
    }
};
5
  • 1
    Please share complete code with state how you are implementing it? Commented Feb 25, 2021 at 15:20
  • you need to provide the rest of your code. Otherwise you could only make guesses about this.state.DATA Commented Feb 25, 2021 at 23:14
  • Inside the class use a constructor() and there declare this.state={isLoading:true, DATA:[]} Commented Feb 26, 2021 at 6:00
  • I tried that but its still not working.@PadminiS Commented Feb 26, 2021 at 6:02
  • 1
    @buzatto I have added the full code. Commented Feb 26, 2021 at 6:09

1 Answer 1

1

The reason it doesn't work is because you have nested promises. The outer then won't wait the inner ones to execute the following code. This way last then with setState is executed without those promises being resolved:

.then((json)=> json.forEach(function(repo,idx){
    // bunch of promises being executed here with some chained then blocks
    // outer 'then' chain doesn't wait these promises to resolve
}))
.then(()=>{
    // since the previous one doesn't wait its inner promises to execute
    // this chained 'then' is executed without those promises return their values
    this.setState({
        repos:repos,
        DATA:issues,
        isLoading:false,
    });

I rewrote your code with async/await because with some many promises it's a hard read. I use Promise.all to wrap all fetches. Also I abstracted your issue treatment to its own normalize function:

  state = { 
    isLoading: true,
    repos: [],
    DATA: [],

  };

  async componentDidMount() {
    const repos = [];
    try {
      const response = await fetch('https://api.github.com/orgs/anitab-org/repos');
      const jsonData = await response.json();
      const DATA = await Promise.all(jsonData.map(async ({ name }) => {
        repos.push(name);
        const issuesResponse = await fetch(`https://api.github.com/repos/anitab-org/${name}/issues`);
        const issuesJSON = await issuesResponse.json();
        const repoIssues = issuesJSON.map(this.normalizeIssue);
        return repoIssues.filter(issue => issue !== undefined);
      }))
      
      // DATA needs to be flat since it's an array of arrays
      this.setState({
        repos,
        DATA: DATA.flat(),
        isLoading:false,
      })
    } catch (error) {
      console.log(error);
    }
  }


  normalizeIssue = (issue) => {
    let flag = false;
    const issueNormalized = {
        id:issue.id.toString(),
        url:issue.html_url,
        title:issue.title,
        milestones:issue.milestones,
        comments:issue.comments,
        number:issue.number,
        assignees:issue.assignees,
        labels:[],
    };
    issue.labels.forEach(function(label){
        if(label.name === "First Timers Only") flag = true;
        issueNormalized.labels.push({
            id:label.id,
            name:label.name,
            color:label.color
        })
    })
    if(flag === true && issueNormalized !== null) return issueNormalized
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.