I am working on a screen which has a button to record audio. And depending on the state of the recording I'd like to hide a text input box which is on the same screen. To hide it I am changing the opacity and making it not editable.
I am setting 2 states (isTextInputEditable
and textInputOpacity
) based on 2 other ones (isRecording
and isRecorded
). I am having issues with my current code because useState is asynchronous and the state of isRecording and isRecorded are not updated when I perform the checks in setTextInputVisibility
function.
Any tips would be helpful, thanks.
const [isTextInputEditable, setIsTextInputEditable] = useState(true);
const [textInputOpacity, setTextInputOpacity] = useState(1);
const [isRecording, setIsRecording] = useState(false);
const [isRecorded, setIsRecorded] = useState(false);
const onRecord = () => {
if (!isRecording) {
console.log("Started recording audio")
setIsRecording(true)
setIsRecorded(false)
}
else {
console.log("Stopped recording audio")
setIsRecording(false)
setIsRecorded(true)
}
setTextInputVisibility();
}
const setTextInputVisibility = () => {
if (!isRecording && !isRecorded){
setIsTextInputEditable(true)
setTextInputOpacity(1)
console.log("Text input visible")
}
else{
setIsTextInputEditable(false)
setTextInputOpacity(0)
console.log("Text input invisible")
}
}
CodePudding user response:
I think your problem is not caused by the asynchronous nature of state, but rather the conflicting conditions:
if (!isRecording && !isRecorded){ ... } // this is the problem
Previously, in the onRecord
function, you set isRecording
and isRecorded
as such:
setIsRecording(true)
setIsRecorded(false)
// or the other way around
This cause !isRecording && !isRecorded
never evaluate to true
, because, there will always be the case that either one of them to will be false
! So isTextInputEditable
and textInputOpacity
will always be false and 0!
Possible fix:
const setTextInputVisibility = () => {
if (!isRecording) { // <- only depends on one state condition
setIsTextInputEditable(true);
setTextInputOpacity(1);
console.log("Text input visible");
} else {
setIsTextInputEditable(false);
setTextInputOpacity(0);
console.log("Text input invisible");
}
};
Again, as tomleb rightful pointed out in the comment, how to manage state is the real issue here, for instance, you may not need textInputOpacity
state at all, since it is basically the same as isTextInputEditable
, and they both serves the same purpose.
Check out sandbox.
CodePudding user response:
You don't have to use state for hiding text input
since hiding text input is dependent on isRecording
and isRecorded
You can do something like this
const [isRecording, setIsRecording] = useState(false);
const [isRecorded, setIsRecorded] = useState(false);
const onRecord = () => {
if (!isRecording) {
console.log("Started recording audio")
setIsRecording(true)
setIsRecorded(false)
}
else {
console.log("Stopped recording audio")
setIsRecording(false)
setIsRecorded(true)
}
setTextInputVisibility();
}
const isTextInputEditable = !isRecording && !isRecorded
const textInputOpacity = (!isRecording && !isRecorded) ? 1 : 0
return (
<View>
{/* Your code goes here */}
<TextInput
disabled={!isTextInputEditable}
style={{ ...styles.inputStyles, opacity : textInputOpacity }}
/>
</View>
)