Home > Mobile >  Why can't I call the parent function passed as props to child component?
Why can't I call the parent function passed as props to child component?

Time:09-13

What I am trying To Do

I am building a simple expo managed audio player app. On my App Screen, I need display a list of songs. When a user clicks on the song, it plays and once the play finishes, the "Songs Played" at the bottom of the page should increase. I am using expo-av API for this.

Here is the breakdown of the app:

App.js

Here I have an array (Data) that holds the songs. To keep it simple, I am using the same song for all elements. count variable holds the count of songs and there is a function (IncreaseCount) which is passed to the ChildComponent as prop. Flatlist is used to render the ChildComponents

import { View, Text, FlatList } from 'react-native'
import React, {useState} from 'react'
import ChildComponent from './ChildComponent';

const Data = [
  {
    key: "1",
    song: "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav"
  },
  {
    key: "2",
    song: "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav"
  },
  {
    key: "3",
    song: "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav"
  }
]


export default function App() {
const [count, setcount] = useState(0);

const IncreaseCount = ()=>{
  setcount(count   1);
}

const renderItem = ({item, index})=>{
  return(
    <View style={{marginTop: 10}} >
  <ChildComponent path={item.path} IncreaseCount={()=>IncreaseCount} index={index} songURL={item.song}/>
  </View>
  )
}


  return (
    <View style={{justifyContent: "center", alignItems: "center", marginTop: 200}}>
      <FlatList
      data={Data}
      renderItem={renderItem}
      extraData={count}
      />
      <Text style={{marginTop: 30}}> Number of Songs Played: {count} </Text>
    </View>
  )
}

ChildComponent

Here I use expo-av API. Using the loadAsync() method, I Initially load the songs upon first render using useEffect hook. Then using onPress method of the button I invoke the playAsync() method of the playBackObject. Using the setOnPlayBackStatusUpdate method, I listen for status changes. When playBackObjectStatus.didJustFinish becomes true, I call the props.IncreaseCount().

import { View, Button } from 'react-native'
import React, {useRef, useEffect} from 'react'
import { Audio } from 'expo-av';

export default function ChildComponent(props) {
const sound = useRef(new Audio.Sound());
const PlayBackStatus = useRef();

useEffect(()=>{
  LoadAudio();
  return ()=> sound.current.unloadAsync()
},[])

const LoadAudio = async ()=>{
  PlayBackStatus.current = sound.current.loadAsync({uri: props.songURL})
  .then((res)=>{
    console.log(`load result : ${res}`)

  })
  .catch((err)=>console.log(err))
}

const PlayAuido = async ()=>{
  PlayBackStatus.current = sound.current.playAsync()
  .then((res)=>console.log(`result of playing: ${res}`))
  .catch((err)=>console.log(`PlayAsync Failed ${err}`))
}

sound.current.setOnPlaybackStatusUpdate(
  (playBackObjectStatus)=>{
    console.log(`Audio Finished Playing: ${playBackObjectStatus.didJustFinish}`)
    if(playBackObjectStatus.didJustFinish){
      console.log(`Inside the If Condition, Did the Audio Finished Playing?: ${playBackObjectStatus .didJustFinish}`)
      props.IncreaseCount();
    }
  }
)

  return (
    <View >
      <Button title="Play Sound" onPress={PlayAuido} />
    </View>
  );
}

Problem I am facing

No matter what I do, I can't get the props.IncreaseCount to be called in App.js. Using console.log inside the if condition of setOnPlayBackStatusUpdate, I know that the props.IncreaseCount() method is being called, but the IncreaseCount() function in App.js is never called. Any help is greatly appreciated!

Here is the snack

CodePudding user response:

Inside here please do this

<ChildComponent path={item.path} IncreaseCount={IncreaseCount} index={index} songURL={item.song}/>

Ive changed IncreaseCount={IncreaseCount}

DO lemme know if this helps

CodePudding user response:

You have two ways to call the IncreaseCount function, in the ChildComponent

<ChildComponent IncreaseCount={IncreaseCount} path={item.path} .......

or

<ChildComponent IncreaseCount={() => IncreaseCount()} path={item.path} .......

CodePudding user response:

You made a mistake while passing increaseCount prop to the ChildComponent

Here are to correct ways to do it:

return(
<View style={{marginTop: 10}} >
  <ChildComponent path={item.path} IncreaseCount={IncreaseCount} index={index} songURL={item.song}/>
</View>

)

or: IncreaseCount={() => IncreaseCount()}

  • Related