0

I'm a newbie in React Native and trying to pass props to ListHeaderComponent in FlatList

Here's the code:

const FirstRoute = (props) => {
  const _renderHeader = () => {
    return(
      <View>
        {props.isFollowed && 
        <TouchableOpacity onPress={props.onSubmit}>
          <Text>You have followed this person</Text>
        </TouchableOpacity> } 
    </View>
    )
  }
  return(
    <View style={[styles.scene, { backgroundColor: '#ff4081' }]}>
    <FlatList
      data={data}
      keyExtractor={item => item.id}
      renderItem={itemData => ( <Image source={itemData.item.id} style={{height: WIDTH/3, width: WIDTH/3}} />)}
      ListHeaderComponent={_renderHeader}
    />
  </View>
  )
};

const SecondRoute = () => (
  <View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
);

const initialLayout = { width: Dimensions.get('window').width };

export default function Parent() {
  const [index, setIndex] = React.useState(0);
  const [routes] = useState([
    { key: 'first', title: 'First' },
    { key: 'second', title: 'Second' },
  ]);
  const [_isFollowed, setIsFollowed] = useState(false);
  const _onSubmit = () => {
    ...
    setIsfollowed(true)

  }

  const renderScene = ({route}) => {
    switch(route.key){
      case 'first': return <FirstRoute {...props} onSubmit={_onSubmit} isFollowed={_isFollowed} />
      case 'second': return <SecondRoute  {...props} />
    }
  };

  return (
    <TabView
      navigationState={{ index, routes }}
      renderScene={renderScene}
      onIndexChange={setIndex}
      initialLayout={initialLayout}
    />
  );
}

But when I save it, the screen logs the error: Can't find the value of isFollowed

I think the problem is at the way I pass the props. I'm still learning it. Since when I delete the ListHeaderComponent, the FlatList still generates the list of images well. And I don't know if it has something to do with renderScene

I really don't understand why

Please help me. Thank you very much

  • Hi Darwin, there are some things going wrong in your code but it is hard to help you out since what you wanna archive wasn't well explained. Please summary what you're trying to implement and I can come up with something helpfull for you. – edilsonlm217 May 05 '20 at 18:29
  • Hi @edilsonlm217 Thank you very much for the response. What I want to do is I can successfully pass the props from the ```Parent``` component down to the ```FirstRoute``` . The props are: ```isFollowed``` ( useState from ```Parent```) and ```onSubmit``` function in ```FirstRoute```. The ```_renderHeader``` will be the JSX that renders the ```ListHeaderComponent``` in my ```FlatList``` –  May 06 '20 at 02:29

1 Answers1

0

Let me get this straight. You need to render _renderHeader dinamically based on _isFollowed state. So, you passed to the first route as props your _onSubmit function and _isFollowed state in order to get to access them at _renderHeader. Right?

As I see you actually doesn't need to do it once your _renderHeader has direct access to both _isFollowed state and _onSubmit function. Try it out as bellow:

export default function Parent() {
  const [index, setIndex] = React.useState(0);
  const [routes] = useState([
    { key: 'first', title: 'First' },
    { key: 'second', title: 'Second' },
  ]);

  const [_isFollowed, setIsFollowed] = useState(false);

  const initialLayout = { width: Dimensions.get('window').width };

  function _onSubmit() {
    setIsFollowed(true);
  }

  function _renderHeader() {
    return (
      <View>
        {_isFollowed && 
        <TouchableOpacity onPress={_onSubmit}>
          <Text>You have followed this person</Text>
        </TouchableOpacity> } 
      </View>
    );
  }

  const FirstRoute = () => {
    return(
      <View style={[styles.scene, { backgroundColor: '#ff4081' }]}>
      <FlatList
        data={data}
        keyExtractor={item => item.id}
        renderItem={itemData => ( <Image source={itemData.item.id} style={{height: WIDTH/3, width: WIDTH/3}} />)}
        ListHeaderComponent={_renderHeader}
      />
    </View>
    )
  };

  const SecondRoute = () => (
    <View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
  );



  const renderScene = ({route}) => {
    switch(route.key){
      case 'first': return <FirstRoute />
      case 'second': return <SecondRoute />
    }
  };

  return (
    <TabView
      navigationState={{ index, routes }}
      renderScene={renderScene}
      onIndexChange={setIndex}
      initialLayout={initialLayout}
    />
  );
}

Other point I don't understand in your code and couldn't check cause I didn't try to run it was the function bellow:

function _renderHeader() {
    return (
      <View>
        {_isFollowed && 
        <TouchableOpacity onPress={_onSubmit}>
          <Text>You have followed this person</Text>
        </TouchableOpacity> } 
      </View>
    );
  }

If you want to render TouchableOpacity just in case _isFollowed is true you should do it using ternary operator like so:

function _renderHeader() {
    return (
        <View>
          {_isFollowed ?  
             <TouchableOpacity onPress={_onSubmit}>
               <Text>You have followed this person</Text>
             </TouchableOpacity> } 
           : <></>
          }
        </View>
    );
}