状态更新,但直到重新渲染后才反映更改

时间:2020-06-23 07:40:33

标签: javascript reactjs

这里是video clip-

pbin.com/kifU2tQY

以下是代码段:

import { Formik, Field } from "formik"
import { useEffect, useState } from "react"

import fetchZipLatLong from "./utils/fetchZipLatLong"
import getLocations from "./utils/getLocations"
import LocationsItem from "./LocationsItem"

const EnterZip = (props) => {
  const { setCustomerZip } = props

  const [loading, setLoading] = useState(false)
  const [locations, setLocations] = useState([])
  const [zipField, setZipField] = useState("")
  // const [userCords, setUserCords] = useState({})
  const [userCordsError, set_userCordsError] = useState(false)

  useEffect(() => {
    const locationsPromise = getLocations()
    locationsPromise.then((res) => {
      setLocations(res.map((location) => location.locationMap.map))
    })
  }, [])

  const handleZipChange = (e) => {
    const newChar = e.target.value
    if (newChar.match(/^[0-9]{0,}$/)) {
      if (newChar.length >= 5) {
        fetchZipLatLong(newChar, process.env.GOOGLE_MAPS_API).then((res) => {
          if (res["error"]) {
            console.log("error true")
            if (!userCordsError) {
              set_userCordsError(true)
            }
          } else {
            console.log("error false")
            set_userCordsError(false)
            console.log(res)
            const { lat, lng } = res

            const locationsByNearest = locations.sort((a, b) => {
              const distanceFirst = Math.sqrt(
                Math.pow(lat - a.latitude, 2) + Math.pow(lng - a.longitude, 2)
              )
              const distanceSecond = Math.sqrt(
                Math.pow(lat - b.latitude, 2) + Math.pow(lng - b.longitude, 2)
              )
              return distanceFirst - distanceSecond
            })

            setLocations(locationsByNearest)
          }
        })
      }
      setZipField(newChar)
    }
  }

  return (
    <div>
      <pre>{JSON.stringify(locations, null, 2)}</pre>
      <h1>Please enter your zip</h1>
      <input
        type="text"
        placeholder="enter your zip to order by closest"
        onChange={handleZipChange}
        value={zipField}
      />
      {userCordsError && <p>Please enter a valid zipcode</p>}
      <button onClick={() => console.log(locations)}>Wow</button>
      {locations.map((location, index) => (
        <LocationsItem location={location} key={index} />
      ))}
    </div>
  )
}

export default EnterZip

我阅读了一些有关异步setState的文章,我猜这是我的问题,但我不知道如何解决。我无法概念化代码中适用的地方

我对代码进行了一些重构,并尝试使用useEffect,但仍然不能解决问题:https://pbin.com/prp227gh

import { Formik, Field } from "formik"
import { useEffect, useState } from "react"

import fetchZipLatLong from "./utils/fetchZipLatLong"
import getLocations from "./utils/getLocations"
import LocationsItem from "./LocationsItem"
import get_locationsByNearest from "./utils/get_locationsByNearest"

const EnterZip = (props) => {
  const { setCustomerZip } = props

  const [loading, setLoading] = useState(false)
  const [locations, setLocations] = useState([])
  const [zipField, setZipField] = useState("")
  // const [userCords, setUserCords] = useState({})
  const [userCordsError, set_userCordsError] = useState(false)

  useEffect(() => {
    const locationsPromise = getLocations()
    locationsPromise.then((res) => {
      setLocations(res.map((location) => location.locationMap.map))
    })
  }, [])

  useEffect(() => {
    console.log(zipField.length)
    if (zipField.length >= 5) {
      fetchZipLatLong(zipField, process.env.GOOGLE_MAPS_API).then((res) => {
        if (res["error"]) {
          console.log("error true")
          if (!userCordsError) {
            set_userCordsError(true)
          }
        } else {
          console.log("error false")
          set_userCordsError(false)
          console.log(res)

          const locationsByNearest = get_locationsByNearest(locations, res)

          setLocations(locationsByNearest)
          console.log(locationsByNearest)
        }
      })
    }
  }, [zipField])

  const handleZipChange = (e) => {
    const newChar = e.target.value

    if (newChar.match(/^[0-9]{0,}$/)) {
      setZipField(newChar)
    }
  }

  return (
    <div>
      <pre>{JSON.stringify(locations, null, 2)}</pre>
      <h1>Please enter your zip</h1>
      <input
        type="text"
        placeholder="enter your zip to order by closest"
        onChange={handleZipChange}
        value={zipField}
      />
      {userCordsError && <p>Please enter a valid zipcode</p>}

      <input
        type="text"
        onChange={() => {
          setLocations([])
        }}
      />

      <button onClick={() => console.log(JSON.stringify(locations, null, 2))}>
        Clear Locations
      </button>

      {locations.map((location, index) => (
        <LocationsItem location={location} key={location.longitude} />
      ))}
    </div>
  )
}

export default EnterZip

设置位置并记录位置后,我确实获得了正确的值。我什至可以设置一个按钮,onClick可以正确打印位置状态。如果我在输入5位数的邮政编码后按了它。但是,尽管该按钮可以打印正确的值,但我的渲染仍然不准确。怎么可能呢?

0 个答案:

没有答案