reactjsreact-nativeforeachreact-hooks

How to solve render error undefined is not a function


My API returns an array of four objects like this:

res = [ { tutor 1 }, { tutor 2 }, { tutor 3 }, { tutor 4 } ]

I loop through them using the for each array method to return a view that contains the information of each tutor but something is wrong.

I get :

render error undefined is not a function (near'...responsee.foreach')

export default  function TutorsScreen ({ navigation }) {

    let [response, setResponse] = useState({});

    useEffect(()  =>  
        fetch("https://elitestudents.link/wp-json/wp/v2/users?role=lp_teacher")
        .then(res => res.json())
        .then((jsoon)=>{
            setResponse(jsoon)
            console.log(jsoon)}
            ))
            
return(
    response.forEach(t => {
        return(
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text
                onPress={() => navigation.navigate('Home')}
                style={{ fontSize: 26, fontWeight: 'bold' }}> 
              tutors names : {t.name} </Text>
             </View>
        )}))}

Solution

  • This happens only on the first render cycle. The function executed in your useEffect is async and will be executed on mount. However, the view will be rendered before the data has been fetched.

    Thus, the response state is an initial empty object. The map function does not exist for an empty object.

    I would use undefined for the initial state and return null until the data has been fetched.

        const [response ,setResponse] =useState();
    
        useEffect(()  => {
          fetch("https://elitestudents.link/wp-json/wp/v2/users?role=lp_teacher")
            .then(res => res.json())
            .then((jsoon) => {
                setResponse(jsoon)
                console.log(jsoon)
            })
        }, [])
    
          if (!response) {
            return null
          }
      return (
        <View>
              {response.map(t => {
            return(
                <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                    <Text
                    onPress={() => navigation.navigate('Home')}
                    style={{ fontSize: 26, fontWeight: 'bold' }}> 
                  tutors names : {t.name} </Text>
                 </View>
            )})}
        </View>
      );
    

    Edit: I might be considered more elegant to use an empty array instead (an empty array defines the map function). In this case we do not need the if statement.

    const [response ,setResponse] =useState([]);
    
        useEffect(()  => {
          fetch("https://elitestudents.link/wp-json/wp/v2/users?role=lp_teacher")
            .then(res => res.json())
            .then((jsoon) => {
                setResponse(jsoon)
                console.log(jsoon)
            })
        }, [])
    
    
      return (
        <View>
              {response.map(t => {
            return(
                <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                    <Text
                    onPress={() => navigation.navigate('Home')}
                    style={{ fontSize: 26, fontWeight: 'bold' }}> 
                  tutors names : {t.name} </Text>
                 </View>
            )})}
        </View>
      );
    

    P.S.: In your question you are using forEach. This won't return the Views. As the comments already suggest, use the map function (although this is not the root of the problem).