>我正在处理一个带有录制音频按钮的屏幕。根据录制的状态,我想隐藏同一屏幕上的文本输入框。为了隐藏它,我正在更改不透明度并使其不可编辑。
我正在根据另外 2 种状态(isRecording
和isRecorded
)设置 2 种状态(isTextInputEditable
和textInputOpacity
)。我当前的代码有问题,因为 useState 是异步的,当我在函数中执行检查时,isRecording 和 isRecorded 的状态setTextInputVisibility
没有更新。
任何提示都会有所帮助,谢谢。
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")
}
}
您不必使用状态来隐藏文本输入 由于隐藏文本输入取决于isRecording
和isRecorded
你可以做这样的事情
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>
)
我认为您的问题不是由状态的异步性质引起的,而是由冲突的条件引起的:
if (!isRecording && !isRecorded){ ... } // this is the problem
以前,在onRecord
函数中,您可以按如下方式设置isRecording
和isRecorded
:
setIsRecording(true)
setIsRecorded(false)
// or the other way around
这个原因!isRecording && !isRecorded
永远无法评估true
,因为,总会有他们中的任何一个都会被false
的情况!所以isTextInputEditable
和textInputOpacity
永远是假的和 0!
可能的解决方法:
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");
}
};
同样,正如 tomleb Rightful 在评论中指出的那样,如何管理状态是这里真正的问题,例如,您可能根本不需要状态textInputOpacity
因为它基本上与isTextInputEditable
相同,并且它们都服务于相同的目的。
查看沙盒。
谢谢大家的回答,这些回答帮助我了解了正在发生的事情。
正如@Enfield所提到的,问题不在于UseState的异步性质。有些条件是错误的,我定义了太多不必要的状态。
我只使用一种状态来解决它,该状态为不同的情况使用枚举,这对于条件渲染非常方便。然后,按照@poojan的建议,我将文本输入可见性变量基于我之前创建的记录状态。此处无需使用效果进行重新渲染。
你可以在这里找到一个工作示例
enum RecordingStatus {
RECORDING = "recording",
RECORDED = "recorded",
NOTRECORDED = "notRecorded",
PLAYING = "playing"
}
export default function App() {
const [recordingStatus, setRecordingStatus] = React.useState<RecordingStatus>(
RecordingStatus.NOTRECORDED
);
const isTextInputEnabled = recordingStatus === RecordingStatus.NOTRECORDED;
const textInputOpacity = isTextInputEnabled ? 1 : 0;
const onRecord = () => {
if (recordingStatus === RecordingStatus.NOTRECORDED) {
console.log("Started recording audio");
setRecordingStatus(RecordingStatus.RECORDING);
} else if (recordingStatus === RecordingStatus.RECORDING) {
console.log("Stopped recording audio");
setRecordingStatus(RecordingStatus.RECORDED);
} else if (recordingStatus === RecordingStatus.RECORDED) {
console.log("Audio playing");
setRecordingStatus(RecordingStatus.PLAYING);
} else if (recordingStatus === RecordingStatus.PLAYING) {
console.log("Audio stopped");
setRecordingStatus(RecordingStatus.RECORDED);
}
};
const onCancel = () => {
console.log("Cancel recording");
setRecordingStatus(RecordingStatus.NOTRECORDED);
};
return (
<div>
<div>isTextInputEditable: {isTextInputEnabled ? "true" : "false"}</div>
<div>textInputOpacity: {textInputOpacity}</div>
<div>recordingStatus: {recordingStatus}</div>
<button onClick={onRecord}>change</button>
<button
disabled={!(recordingStatus === RecordingStatus.RECORDED)}
onClick={onCancel}
>
cancel
</button>
</div>
);
}