数组上的 React setState 在调用后立即将值重置为 null(功能组件)

React setState on array resets value to null right after call (Functional component)

很抱歉问这个问题,但经过一整天的研究,我仍然不明白为什么,但是当我在我的数组上调用 setState 时,值立即返回到 null。 我的代码工作了,然后我不得不将我的组件变成一个功能组件来使用 MaterialUI,它停止工作了。我试过用useEffect,钩子里的值是好的,但是马上又回到初始值。

(有问题的变量是标记,它总是返回 [null, null])

可能是因为我正在存储一个对象?

代码:

import React, { useState, useEffect } from 'react';
import $ from 'jquery'
import { makeStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';

import './app.css'
import Map from './Map'
import PlaceSearch from './PlaceSearch'
import { useReducer } from 'react';

function NewTrip () {
  const [mapCenter, setMapCenter] = useState([50.631290, 3.062750])
  const [markers, setMarkers] = useState([null, null])
  const [zoom, setZoom] = useState(13)

  // const initialState = {markers: [null, null]}
  // const [state, dispatch] = useReducer(reducer, initialState)

  // Load leaflet icons for markers
  const redIcon = new L.Icon({
    iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
    shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
    iconSize: [25, 41],
    iconAnchor: [12, 41],
    popupAnchor: [1, -34],
    shadowSize: [41, 41]
  });
  const blueIcon = new L.Icon({
    iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-blue.png',
    shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
    iconSize: [25, 41],
    iconAnchor: [12, 41],
    popupAnchor: [1, -34],
    shadowSize: [41, 41]
  }); 

  useEffect(() => {
    debugger
  })

  const departChanged = (e) => {
    var selectedPoint = e.suggestion.latlng
    var newMarkers = {...markers}

    newMarkers[0] = new L.marker(selectedPoint, {icon: blueIcon})
    setMapCenter([selectedPoint.lat, selectedPoint.lng])
    setMarkers(newMarkers)
    //dispatch({type: 'set_markers', payload: newMarkers})
    debugger
  }

  const arrivalChanged = (e) => {
    var selectedPoint = e.suggestion.latlng
    var newMarkers = {...markers}

    newMarkers[1] = new L.marker(selectedPoint, {icon: redIcon})
    setMapCenter([selectedPoint.lat, selectedPoint.lng])
    setMarkers(newMarkers)
  }

  //const classes = useStyles()

  return (
    <div>
      <h1 className="text-centered">Nouveau trajet</h1>
      <br/>
      <div className="split left">
        <div className="center">
          <PlaceSearch suggestionChanged={departChanged} placeholder={"Départ"} inputId={"departSearch"}></PlaceSearch>
          <PlaceSearch suggestionChanged={arrivalChanged} placeholder={"Arrivée"} inputId={"arrivalSearch"}></PlaceSearch>
          {/* <Map center={mapCenter} markers={markers} zoom={zoom}></Map> */}
        </div>
      </div>
      <div className="split right">
        <div className="center">
          <h2>Places disponibles</h2>
          <input id="seats" type="number" max="9" min="1" defaultValue="2"/>
          <p>(Min 1, Max 9)</p>
          <br/>
          <br/>
        </div>
      </div>
    </div>
  );
}

export default NewTrip;

如您所见,我什至尝试使用 reducer 而不是 state,但结果是一样的。

=====更新=====

好的,经过一些研究,该值设置正确,但从 dapartChanged 和 arrivalChanged 函数内部或外部访问时,该值不同。函数外面的值是正常的,里面的值总是 Array [null, null]

要使用 setMarkers 更改现有数组中的特定元素,您可以执行

const departChanged = (e) => {
  var selectedPoint = e.suggestion.latlng
  setMapCenter([selectedPoint.lat, selectedPoint.lng])
  setMarkers((prev) => [new L.marker(selectedPoint, {icon: blueIcon}), prev[1]])
}

const arrivalChanged = (e) => {
  var selectedPoint = e.suggestion.latlng
  setMapCenter([selectedPoint.lat, selectedPoint.lng])
  setMarkers((prev) => [prev[0], new L.marker(selectedPoint, {icon: redIcon})])
}

您将标记散布到一个对象中,然后像调用数组一样调用它。

const arrivalChanged = (e) => {
    var selectedPoint = e.suggestion.latlng
    var newMarkers = {...markers} /*<==== should probably be const newMarkers = [...markers];*/

    newMarkers[1] = new L.marker(selectedPoint, {icon: redIcon})
    setMapCenter([selectedPoint.lat, selectedPoint.lng])
    setMarkers(newMarkers)
  }

如果仍然失败,请在使用 setMarkers 之前 console.log(newMarkers) 以便我们查看数据。

真正的问题是我从子组件调用 departChanged 和 arrivalChanged 方法,显然在那个上下文中我访问的所有值都是默认状态值。

我不知道如何修复它,但现在我用 useRef 替换了它并且它有效。

如果有人知道为什么当函数被另一个组件调用时状态值是默认值,请发表评论^^