我有一个使用useState()
来处理其浮动标签状态的组件,如下所示:
const FloatingLabelInput = props => {
const {
value = ''
} = props
const [floatingLabel, toggleFloatingLabel] = useState(value !== '')
我有一系列这些组件,您期望initialFloatingLabel
和floatingLabel
总是相同的,但是它们并不适合其中的一些!我可以通过记录值来查看:
const initialFloatingLabel = value !== ''
console.log(initialFloatingLabel) // false
const [floatingLabel, toggleFloatingLabel] = useState(initialFloatingLabel)
console.log(floatingLabel) // true???
这是一个一致的结果。那怎么可能?
在以下示例中,value
与initialValue
有何不同?这是一种比赛条件吗?
const [value, setValue] = useState(initialValue)
更多详细信息here
更新
此(as suggested)解决了问题:
useEffect(() => setFloatingLabel(initialFloatingLabel), [initialFloatingLabel])
...但是它创建了另一个:如果我专注于一个字段,则键入一些内容然后将其删除,直到该值是一个空字符串,它将像这样将标签“浮动”(标签应该是浮动的) :
我不打算一直根据输入的floatingLabel
更新value
状态; initialFloatingLabel
的值仅用于指示切换的初始值,我将在handleBlur
和handleChange
事件中进行切换,如下所示:
const handleFocus = e => {
toggleFloatingLabel(true)
}
const handleBlur = e => {
if (value === '') {
toggleFloatingLabel(false)
}
}
这种方法错误吗?
更新
我一直在寻找新的解决方案,但始终存在一个持续存在的问题,我想说这是Formik的问题-似乎最初是在完全根据Formik的{ {1}}。
例如:
我添加了另一个本地状态,并在initialValues
和handleFocus
上进行了更新:
handleBlur
因此我可以这样做,以防止在输入为空但集中时使标签浮动:
const [isFocused, setFocused] = useState(false)
我仍然会这样做,以防止预先填充的字段在标签上的动画从非浮动变为浮动(我为此使用useEffect(() => {
const shouldFloat = value !== '' && !isFocused
setFloatLabel(shouldFloat)
}, [value])
)
react-spring
但是我仍然会在标签上获得动画(从“浮动”到“非浮动”),这些是我在此线程开头指出的那些特定字段的,这些字段没有预先填充。
根据评论中的建议,我完全放弃了const [floatLabel, setFloatLabel] = useState(value !== '')
本地状态,只是保留了floatingLabel
本地状态。太好了,我真的不需要它,我只能将它用于标签动画:
isFocused
现在代码看起来更干净了,但是我不应该在标签上放一个动画(对于我一开始提到的那些相同的特定值),因为const animatedProps = useSpring({
transform: isFocused || value !== '' ? 'translate3d(0,-13px,0) scale(0.66)' : 'translate3d(0,0px,0) scale(1)',
config: {
tension: 350,
},
})
等于value !== ''
出于某些晦涩的原因,在第一次渲染时又重新进入true
。
设置字段的初始值时,Formik出现了问题吗?
答案 0 :(得分:1)
当useEffect
更改时,您可以使用initialFloatingLabel
更新状态。
const initialFloatingLabel = value !== ''
const [floatingLabel, setFloatingLabel] = useState(initialFloatingLabel)
// calling the callback when initialFloatingLabel change
useEffect(() => setFloatingLabel(initialFloatingLabel), [initialFloatingLabel])
...
您的问题看起来像是道具钻探问题。也许您应该将floatingLabel
存储在context
中。
// floatingLabelContext.js
import { createContext } from 'react'
export default createContext({})
// top three component
...
import { Provider as FloatingLabelProvider } from '../foo/bar/floatingLabelContext'
const Container = () => {
const [floatingLabel, setFloatingLabel] = useState(false)
return (
<FloatingLabelProvider value={{ setFloatingLabel, floatingLabel }}>
<SomeChild />
</FloatingLabel>
)
}
// FloatingLabelInput.js
import FloatingLabelContext from '../foo/bar/floatingLabelContext'
const FloatingLabelInput = () => {
const { setFloatingLabel, floatingLabel } = useContext(FloatingLabelContext)
...
}
这样,您只需要使用上下文即可在三个组件中所需的位置更改或读取floatLabel值。