useState()错误-状态值与初始值不同

时间:2019-09-12 13:42:29

标签: reactjs react-hooks formik

我有一个使用useState()来处理其浮动标签状态的组件,如下所示:

const FloatingLabelInput = props => {
  const {
    value = ''
  } = props

  const [floatingLabel, toggleFloatingLabel] = useState(value !== '')

我有一系列这些组件,您期望initialFloatingLabelfloatingLabel总是相同的,但是它们并不适合其中的一些!我可以通过记录值来查看:

const initialFloatingLabel = value !== ''
console.log(initialFloatingLabel) // false
const [floatingLabel, toggleFloatingLabel] = useState(initialFloatingLabel)
console.log(floatingLabel) // true???

这是一个一致的结果。那怎么可能?

在以下示例中,valueinitialValue有何不同?这是一种比赛条件吗?

const [value, setValue] = useState(initialValue)

更多详细信息here

更新

此(as suggested)解决了问题:

useEffect(() => setFloatingLabel(initialFloatingLabel), [initialFloatingLabel])

...但是它创建了另一个:如果我专注于一个字段,则键入一些内容然后将其删除,直到该值是一​​个空字符串,它将像这样将标签“浮动”(标签应该是浮动的) :

enter image description here

我不打算一直根据输入的floatingLabel更新value状态; initialFloatingLabel的值仅用于指示切换的初始值,我将在handleBlurhandleChange事件中进行切换,如下所示:

const handleFocus = e => {
  toggleFloatingLabel(true)
}

const handleBlur = e => {
  if (value === '') {
    toggleFloatingLabel(false)
  }
}

这种方法错误吗?

更新

我一直在寻找新的解决方案,但始终存在一个持续存在的问题,我想说这是Formik的问题-似乎最初是在完全根据Formik的{ {1}}。

例如:

我添加了另一个本地状态,并在initialValueshandleFocus上进行了更新:

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出现了问题吗?

1 个答案:

答案 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值。