1

so i want to load some data from my server using axios in React native. The data was retrieved successfully, but i don't know how to display it on the page. When i click button 'Load students' it does axios get method and after that calls method 'showStudents' but that method doesn't return anything. I really don't understand how rendering works in react native so i would appreciate any help and guidance. Also if there is easier way to do all of this, i'm open for suggestions.

export default function Students() {
const [s, setStudents] = useState('')

const getStudents = async () => {
    try{
        const {data: {students}} = await axios.get('http://192.168.1.2:3000/api/v1/students')
        setStudents(students)
        //console.log(students)
        showStudents()
    }
    catch(error){
        console.log(error)
    }
}

const showStudents = () => {
    
    return( <ScrollView>
            {
                s.map((student) => (
                    <ListItem key={student._id} bottomDivider>
                        <ListItem.Content>
                            <ListItem.Title>{student.firstName}</ListItem.Title>
                            <ListItem.Subtitle>{student.index}</ListItem.Subtitle>
                        </ListItem.Content>
                    </ListItem>
                ))
            }
        </ScrollView>)
    
}


return (
    <View style={styles.container}>
        <Button title='Load students' color='green' onPress={getStudents}/>
    </View>
);

}

1 Answers1

3

The function showStudents returns a JSX component, but not inside of the render function of the component Students.

You can just create a new JSX component and use conditional rendering in order to render it whenever the state s (I would call it students) is not undefined and has a length strictly greater than zero.

const [students, setStudents] = useState()

const getStudents = async () => {
    try{
        const {data: {students}} = await axios.get('http://192.168.1.2:3000/api/v1/students')
        setStudents(students)
    }
    catch(error){
        console.log(error)
    }
}

return (
    <View style={styles.container}>
        <Button title='Load students' color='green' onPress={getStudents}/>
        {
            students && students.length > 0 ? <ScrollView>
            {
                students.map((student) => (
                    <ListItem key={student._id} bottomDivider>
                        <ListItem.Content>
                            <ListItem.Title>{student.firstName}</ListItem.Title>
                            <ListItem.Subtitle>{student.index}</ListItem.Subtitle>
                        </ListItem.Content>
                    </ListItem>
                ))
            }
           </ScrollView> : null
        }
    </View>
);

We could create a new component to make things more structured. Let us introduce StudentList.

export function StudentList({students}) {
    return <ScrollView>
            {
                students.map((student) => (
                    <ListItem key={student._id} bottomDivider>
                        <ListItem.Content>
                            <ListItem.Title>{student.firstName}</ListItem.Title>
                            <ListItem.Subtitle>{student.index}</ListItem.Subtitle>
                        </ListItem.Content>
                    </ListItem>
                ))
            }
           </ScrollView> 
}

Then, reuse this new component.

const [students, setStudents] = useState()

const getStudents = async () => {
    try{
        const {data: {students}} = await axios.get('http://192.168.1.2:3000/api/v1/students')
        setStudents(students)
    }
    catch(error){
        console.log(error)
    }
}

return (
    <View style={styles.container}>
        <Button title='Load students' color='green' onPress={getStudents}/>
        {
            students && students.length > 0 ? <StudentList students={students} /> : null
        }
    </View>
);
David Scholz
  • 8,421
  • 12
  • 19
  • 34
  • Great, that works. Thank you so much for your help. Also another question regarding this, is there any way i could fetch data when i load this page without pressing the button? I read something about using useEffect method but if it's possible can you explain what that does? – Igor Karadzic Dec 13 '22 at 01:40
  • Yes, this is possible. Create an effect with an empty dependency array, then it will be called on mount of the component. Check the answers for [this question](https://stackoverflow.com/questions/53332321/react-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret) to get an idea. But check the accepted answer, and do not use some third party lib as suggested by others. – David Scholz Dec 13 '22 at 09:33
  • I have tried using useEffect for the the question you've given me but when i open that page(i put log inside) is calls my fetch function infinite times. Is there any ways i can fix this? `const getStudents = useCallback(async () => { try{ const {data: {students}} = await axios.get('http://192.168.1.2:3000/api/v1/students') setStudents(students) } catch(error){ console.log(error) } }, [students]) useEffect(() => { console.log('asd') getStudents() }, [getStudents])` – Igor Karadzic Dec 13 '22 at 17:24
  • `students` from the axis response is unrelated to the `students` state. You need to remove `students` from the dependency array. Leave it empty: `React.useEffect(() => { .... setStudents(students) }, [])` – David Scholz Dec 14 '22 at 08:43
  • It fiexs that part, but what do i have to do to make it so that when i add/update a student in my database and get back on the page where it fetches all students again because there was a change. Again i read that dependency array has soemthing to do with that(maybe i'm wrong) but i tried every scenario i could think of and it doesn't work. – Igor Karadzic Dec 14 '22 at 17:21
  • Use a focus effect for this scenario. Refetch on focus gain. – David Scholz Dec 14 '22 at 17:53