Javascript 当我键入其他组件的输入框时,React Mapbox组件闪烁
我想在一个页面上有一个地图和一个输入表单。用户应该能够在输入字段中键入,点击submit,并让Mapbox组件移动到该位置 我有两个问题,我怀疑它们是相关的。当我在输入框中键入时,映射组件在每次onChange事件后闪烁。其次,当我提交表单时,地理位置被成功获取,道具在地图组件上更新,地图标记出现,但地图没有执行我在进入React Dev tools并手动更新道具时看到的整洁动画 我知道我是一个初学者,我肯定这有一千件事是错误的。如果有人知道答案,我会很高兴,但如果有人能给我指出正确的方向,我也会很高兴。我花了一上午的时间浏览了React的“入门”和“挂钩”部分,并参加了一些React课程,在这些课程中,你构建了简单的应用程序,但显然有些基本的东西没有被理解。谢谢 以下是下一页:Javascript 当我键入其他组件的输入框时,React Mapbox组件闪烁,javascript,reactjs,react-hooks,react-component,react-state,Javascript,Reactjs,React Hooks,React Component,React State,我想在一个页面上有一个地图和一个输入表单。用户应该能够在输入字段中键入,点击submit,并让Mapbox组件移动到该位置 我有两个问题,我怀疑它们是相关的。当我在输入框中键入时,映射组件在每次onChange事件后闪烁。其次,当我提交表单时,地理位置被成功获取,道具在地图组件上更新,地图标记出现,但地图没有执行我在进入React Dev tools并手动更新道具时看到的整洁动画 我知道我是一个初学者,我肯定这有一千件事是错误的。如果有人知道答案,我会很高兴,但如果有人能给我指出正确的方向,我也
import ReactMapboxGl, { Marker } from 'react-mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import { useState } from 'react';
export default function TestPage() {
const Map = ReactMapboxGl({
accessToken: process.env.NEXT_PUBLIC_MAPBOX,
});
const [searchLocation, setSearchLocation] = useState('');
const [geolocate, setGeolocate] = useState({
coordinates: [2.61878695312962, 47.8249046208979],
isPin: false,
});
async function fetchGeolocate(location) {
const url = `https://api.mapbox.com/geocoding/v5/mapbox.places/${location}.json?access_token=${process.env.NEXT_PUBLIC_MAPBOX}`;
fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then((myText) => {
const json = JSON.parse(myText);
const coordinates = json.features[0].center;
setGeolocate({ coordinates, isPin: true });
});
}
function handleInputChange(event) {
setSearchLocation(event.target.value);
}
function handleForm(e) {
e.preventDefault();
fetchGeolocate(searchLocation);
}
return (
<>
<Map
style="mapbox://styles/mapbox/streets-v11"
containerStyle={{
height: '50vh',
width: '100vw',
}}
center={geolocate.coordinates}
zoom={[3]}
>
{geolocate.isPin && (
<Marker coordinates={geolocate.coordinates}>
<span className="text-3xl" role="img" aria-label="push-pin">
Your sense that the problems are related is right on. One issue is that you're re-initializing the Map
component on every render:
const Map = ReactMapboxGl({
accessToken: process.env.NEXT_PUBLIC_MAPBOX,
});
从'react mapbox gl'导入ReactMapboxGl,{Marker};
导入“mapbox gl/dist/mapbox gl.css”;
从“react”导入{useState};
导出默认函数TestPage(){
const Map=ReactMapboxGl({
accessToken:process.env.NEXT\u PUBLIC\u映射框,
});
const[searchLocation,setSearchLocation]=useState(“”);
const[geologite,setgeologite]=useState({
座标:[2.61878695312962,47.8249046208979],
伊斯宾:错,
});
异步函数FetchGeoLocation(位置){
常量url=`https://api.mapbox.com/geocoding/v5/mapbox.places/${location}.json?access_token=${process.env.NEXT_PUBLIC_MAPBOX}`;
获取(url)
。然后((响应)=>{
如果(!response.ok){
抛出新错误(`HTTP错误!状态:${response.status}`);
}
返回response.text();
})
。然后((myText)=>{
const json=json.parse(myText);
const coordinates=json.features[0].center;
setgeologite({坐标,isPin:true});
});
}
函数handleInputChange(事件){
setSearchLocation(事件、目标、值);
}
功能手柄(e){
e、 预防默认值();
fetchgeologite(searchLocation);
}
返回(
{geologite.isPin&&(
您对问题相关的感觉是正确的。一个问题是您正在初始化每个渲染上的Map
组件:
const [map, setMap] = useState()
useEffect(() => {
const mapInit = ReactMapboxGl({
accessToken: process.env.NEXT_PUBLIC_MAPBOX,
})
setMap(mapInit)
}, [])
它还将阻止动画的发生(我认为),因为它将创建映射的新实例,这将导致React unmount/remount组件
编辑:下面OP的答案:在组件外部初始化
看起来您可以在任何渲染逻辑之外初始化组件
替代方法:使用状态
在功能组件中,我们希望将初始化逻辑放入(或者如果它发生在第一次渲染之前非常重要,useLayoutEffect
)
最后的[]
是关键。它防止我们的回调在第一次调用后被调用
老实说,您的组件可能非常复杂,足以保证使用类组件,您可以使用componentDidMount
进行初始化,并且不必在每次渲染时重新计算所有这些助手函数。不过最终还是由您决定
最后一点注意:您已将fetchgeologe
声明为async
,这意味着不调用。然后在所有结果上,如果您愿意,可以使用wait
。或者取消async
&继续使用承诺。然后
,这取决于您。这可能有助于澄清差异。as@elhil s在上面的帮助下,问题基本上是我在每次渲染时重新初始化贴图。所做的只是将贴图组件初始化移出主函数。我还听取了@elhil的建议并修复了我的异步等待函数。下面的代码
从'react mapbox gl'导入ReactMapboxGl,{Marker};
导入“mapbox gl/dist/mapbox gl.css”;
从“react”导入{useState};
const Map=ReactMapboxGl({
accessToken:process.env.NEXT\u PUBLIC\u映射框,
});
导出默认函数TestPage(){
const[searchLocation,setSearchLocation]=useState(“”);
const[geologite,setgeologite]=useState({
座标:[2.61878695312962,47.8249046208979],
伊斯宾:错,
});
异步函数FetchGeoLocation(位置){
常量url=`https://api.mapbox.com/geocoding/v5/mapbox.places/${location}.json?access_token=${process.env.NEXT_PUBLIC_MAPBOX}`;
const response=等待获取(url);
如果(!response.ok){
抛出新错误(`HTTP错误!状态:${response.status}`);
}
const json=await response.json();
const coordinates=json.features[0].center;
setgeologite({坐标,isPin:true});
}
函数handleInputChange(事件){
setSearchLocation(事件、目标、值);
}
功能手柄(e){
e、 预防默认值();
fetchgeologite(searchLocation);
}
返回(
{geologite.isPin&&(
也可以考虑使用LooStudio库。这可以防止每次有人在快速输入中键入某些东西而发送请求。只有在短暂的停顿之后,才触发触发地理位置的请求。哇,这都是非常有帮助的。游荡在荒野中,很难看到你什么时候丢失了踪迹。我有一个问题。我所使用的指令是基于钩子的,而React编写的材料是基于类的。现在我很清楚,如果不同时学习这两种方法,我是不会逃脱的。让我尝试一下这些建议。非常感谢您的帮助!您的建议让我找到了解决方案。我无法将地图置于状态,也不确定这是否会发生这是一个好主意,因为地图本身就是一个组件,从我收集的信息来看