数组上的 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 替换了它并且它有效。
如果有人知道为什么当函数被另一个组件调用时状态值是默认值,请发表评论^^
很抱歉问这个问题,但经过一整天的研究,我仍然不明白为什么,但是当我在我的数组上调用 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 替换了它并且它有效。
如果有人知道为什么当函数被另一个组件调用时状态值是默认值,请发表评论^^