0

I have a screen which should display a result of search. So, I created my fetch in the render(). As describing in this stackoverflow response, I pushed my response in an array. In the console panel, the result array is loading after some seconds but in my screen, the result array still empty.

This is my render function

render() {
        let result = [];
        let endPoint = this.props.navigation.getParam('endPoint', '');
        fetch(endPoint, {
            method: "GET",
            headers: null,
        }).then(response => response.json())
            .then(response => {
                let list = response;
                for (let i = 0; i < list.length; i++) {
                    result.push(
                        <View key={i} style={styles.item}>
                            <View>
                                <View style={styles.imageContainer}>
                                    <Image style={styles.imageItem} resizeMode="cover"
                                           source={{uri: list[i].img}}/>
                                </View>
                            </View>
                            <View style={styles.inlineDetails}>
                                <Text style={styles.innerTitle}>
                                    {list[i].lieugeo}
                                </Text>
                                <Text style={styles.innerDescription}>
                                    {list[i].desc.substring(0, 80)}
                                </Text>

                            </View>
                        </View>
                    )
                }
            }).catch((error) => {
            console.error(error);
        });

        return (
            <ImageBackground source={require('./images/internal_bg.png')} style={{width: '100%', height: '100%'}}>
                <ScrollView>
                    <View style={styles.container}>
                        {result}
                    </View>
                </ScrollView>
            </ImageBackground>
        );
    }

Expected result: a list of items is displayed Actual result: the screen still empty

A.Sana
  • 95
  • 2
  • 14

2 Answers2

0

Your problem here is that fetch is asynchronous. So render won't wait for it to complete before it renders the component. You should do your data retrieval in componentDidMount and modify the component state with the result. Then use this state in your render method to populate your items (your component will re-render once you change the state). You should also set your initial state in the component constructor method.

Like below:


    constructor(props) {
        super(props)
        this.state = { list: [] }
    }

    componentDidMount() {
        let endPoint = this.props.navigation.getParam('endPoint', '');
        fetch(endPoint, {
            method: "GET",
            headers: null,
        })
        .then(response => response.json())
        .then(response => {
            this.setState({ list: response })            
        })
        .catch((error) => {
            console.error(error);
        });
    }

    render() {
            let result = [];
            const { list } = this.state;

            for (let i = 0; i < list.length; i++) {
                result.push(
                    <View key={i} style={styles.item}>
                        <View>
                            <View style={styles.imageContainer}>
                                <Image style={styles.imageItem} resizeMode="cover"
                                       source={{uri: list[i].img}}/>
                            </View>
                        </View>
                        <View style={styles.inlineDetails}>
                            <Text style={styles.innerTitle}>
                                {list[i].lieugeo}
                            </Text>
                            <Text style={styles.innerDescription}>
                                {list[i].desc.substring(0, 80)}
                            </Text>

                        </View>
                    </View>
                )
            }

            return (
                <ImageBackground source={require('./images/internal_bg.png')} style={{width: '100%', height: '100%'}}>
                    <ScrollView>
                        <View style={styles.container}>
                            {result}
                        </View>
                    </ScrollView>
                </ImageBackground>
            );
        }

Jono
  • 627
  • 4
  • 8
0

Always perform side-efects in componentDidMount(){} then update the component state or redux store. Also you can use response array and create an separate child component to display the result of that array.

This way your code is more reusable es

render(){
<View>
{this.state.data && this.state.data.map(item => <DisplayProduct data={item}/>)}
<View/>
}

Here Display product accept one item at a time as props, when ever the state updates the child component also gets updated and This component can be re used anywhere inside your app.

Raj D
  • 485
  • 1
  • 5
  • 11