I have a group of react-native components that have similar interfaces. The important method in the interface is the run method. Users can execute this run method by pressing an action button for each of the components or by pressing an action button in the parent level, that will iterate through each of these similar components using their ref and call the run method. Here is a simplified version of the setup.
const Test1 = forwardRef((props, ref) => {
const [importantState, setimportantState] = useState('initial')
useImperativeHandle(ref, () => ({
run: run,
}))
const run = async () => {
// This function will open a modal
// where users will eventually change the important state
openInteractionModal()
// The idea of this promiss is to settle when the users
// eventually change the importantState thorugh thier interaction
// It does so by checking the state every 100 miliseconds
// This however is a problem as a result of the setInterval function will
// inclose the initial state instead of getting the new value each time
return new Promise((resolve, reject) => {
let interval = setInterval(() => {
if (importantStat === 'complete') {
resolve('success')
clearInterval(interval)
} else if (importantStat === 'failed') {
reject('failed')
clearInterval(interval)
}
}, 100)
})
}
return (
<>
<Button title="run" onPress={run} />
</>
)
})
const parentComponent = () => {
const test1Ref = userRef(null)
const test2Ref = userRef(null)
const test3Ref = userRef(null)
const testRefs = [test1Ref, test2Ref, test3Ref]
const autoRun = async () => {
testRefs.forEach(ref => {
await ref?.current.run()
});
}
return (
<>
<Button title="Auto run" onPress={autoRun} />
<Test1 ref={test1Ref} />,
<Test2 ref={test2Ref} />,
<Test3 ref={test3Ref} />,
</>
)
}
The problem I am having right now is the promise I am returning from these individual components never settles as a result of the closure I mentioned above in the comments. Is there a way to overcome this closure, or is there a better react-native pattern that I am using right now?
2
Answers
Create a ref and store the status in that instead of the state of the Test1 component.
Like that
Set value in the current of the ref
Later use it in the setInterval like
Don’t go polling. Instead, pass the
resolve
function as an argument toopenInteractionModal
, and call it together withsetImportantState
from the modal dialog.If that is for some reason not possible, you can use a ref to store the
resolve
function and run it from an effect when the state changes: