对不起,我问了这个问题,但经过一整天的研究,我仍然不明白为什么当我在数组上调用setState时,值会马上返回到null。我的代码工作了,然后我不得不把我的组件变成一个功能组件来使用MaterialUI,它停止工作。我试着使用useEffect,钩子中的值是好的,但之后马上又回到初始值。
(问题变量是markers,它总是回到[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和arrivateChanged函数里面访问时,值是不一样的,还是在函数外面。在函数外的值是正常的,在函数内的值总是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)
}
如果还是不行,请 console.log(newMarkers)
使用前 setMarkers
所以我们可以看到数据是什么样子的。
真正的问题是我从一个子组件中调用departChanged和arrivationChanged方法,显然在那个上下文中,我访问的所有值都是默认状态值。
我不知道如何解决这个问题,但目前我用useRef替换了它,它可以工作。
如果有人知道为什么当函数被其他组件调用时,状态值是默认值,请留言^^。