在 React/Next.js 中,如何简单地将数据从一个页面的组件传递到另一个页面的组件?
How can I simply pass data from a component one page to a component on another page in React/Next.js?
总结
我有一个简单的 next.js 应用程序,有两个页面,index.js 和 results.js。索引页面有两个位置自动完成字段,在用户从推荐位置的下拉列表中选择位置后,return 位置的地址和 LatLng。 return 编辑后,此数据将存储在索引页上名为 markers
的变量中。当用户单击索引页面上的 Get Results 按钮时,我试图将地址和 LatLng 数据传递到结果页面,以便所选位置可以显示为标记在地图上。
问题
我已经断断续续地尝试了大约一个星期,但我不知道如何实现我想要的。我觉得应该有一个超级简单的方法来做到这一点,但我就是想不通。我试过类似的东西:
- 在单击按钮时传递数据彻底的请求参数,但是 link 是在页面呈现时根据变量值生成的,而不是在更新变量时更新
- 将地图与位置自动完成放在同一页面上并尝试使用状态自动重新加载地图,这对我来说似乎根本不起作用
- 我也研究过 Redux,但这似乎太复杂了,无法简单地将 object/it 的数据从一个页面传递到另一个页面
我理想的解决方案是将数据从 indext 传递到结果的简单方法。可能还值得指出的是,我是 React/Next.js 的新手,所以我可能会以错误的方式处理所有这些问题,一旦它起作用,我还将添加一个 API调用以获取两个 LatLng 点之间的方向,这也将显示在结果页面的地图上。
代码
index.js(简体)
{/* Import used next and style objects */ }
import Head from 'next/head'
import styles from '../styles/Home.module.css'
{/* Import react-bootstrap */ }
import { Container, Row, Col } from 'react-bootstrap'
{/* Import geosuggest */ }
import Geosuggest from 'react-geosuggest'
{/* Import used components */ }
import NavigationBar from '../components/NavigationBar'
import Footer from '../components/Footer'
{/* Import and use runtime vars for Google API */ }
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
const GoogleApiUrl = `https://maps.googleapis.com/maps/api/js?key=${publicRuntimeConfig.MAPS_JAVASCRIPT_API_KEY}&libraries=places`
export default function Home() {
const markers = {
from: {description: "", lat: 0, lng: 0},
to: {description: "", lat: 0, lng: 0}
}
const onFromSuggestSelect = (suggest) => {
console.log("New FROM location selected: \"" + suggest.description + "\"");
markers.from.description = suggest.description
markers.from.lat = suggest.location.lat
markers.from.lng = suggest.location.lng
}
const onToSuggestSelect = (suggest) => {
console.log("New TO location selected: \"" + suggest.description + "\"");
markers.to.description = suggest.description
markers.to.lat = suggest.location.lat
markers.to.lng = suggest.location.lng
}
return (
<div>
<Head>
<title>MyApp</title>
<meta name="description" content="MyApp" />
<link rel="icon" href="/favicon.ico" />
<script src={GoogleApiUrl}></script>
</Head>
<NavigationBar/>
<div className={styles.container}>
<main>
<Container>
<Row className="text-center">
<Col md={1}></Col>
<Col md={5}><Geosuggest data-test-id="autocomplete-start-test" placeholder="From..." onSuggestSelect={onFromSuggestSelect} country="gb" minLength="3" /></Col>
<Col md={5}><Geosuggest data-test-id="autocomplete-end-test" placeholder="To..." onSuggestSelect={onToSuggestSelect} country="gb" minLength="3" /></Col>
<Col md={1}></Col>
</Row>
</Container>
</main>
<Footer/>
</div>
</div>
)
}
results.js(简体)
{/* Import used next and style objects */ }
import Head from 'next/head'
import styles from '../styles/Home.module.css'
{/* Import used react-bootstrap objects */ }
import { Container } from 'react-bootstrap'
{/* Import used components */ }
import NavigationBar from '../components/NavigationBar'
import Footer from '../components/Footer'
import Map from '../components/Map'
{/* Import and use runtime vars for Google API */ }
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
const GoogleApiUrl = `https://maps.googleapis.com/maps/api/js?key=${publicRuntimeConfig.MAPS_JAVASCRIPT_API_KEY}&libraries=places`
export default function Home() {
const markers = {
from: {description: "", lat: 0, lng: 0},
to: {description: "", lat: 0, lng: 0}
}
return (
<div>
<Head>
<title>MyApp</title>
<meta name="description" content="MyApp" />
<link rel="icon" href="/favicon.ico" />
<script src={GoogleApiUrl}></script>
</Head>
<NavigationBar/>
<div className={styles.container}>
<main>
<Container>
{/* MARKERS NEEDS TO BE PASSED IN ON THE LINE BELOW */}
<Map markers={markers}/>
</Container>
</main>
</div>
<Footer/>
</div>
)
}
Map.js(分量)
import React from "react"
import { GoogleMap, Marker } from "@react-google-maps/api"
export default class Map extends React.Component {
render() {
// Set the map to fill its container
const containerStyle = { width: '500px', height: '500px' }
// Set the map to show the entire UK on initial load
const center = { lat: 54.476422, lng: -3.397340 }
const zoom = 6
// Return the map with the above defaults
return(
<GoogleMap mapContainerStyle={containerStyle} center={center} zoom={zoom}>
<Marker position={{ lat: this.props.markers.from.lat, lng: this.props.markers.from.lng }} />
<Marker position={{ lat: this.props.markers.to.lat, lng: this.props.markers.to.lng }} />
</GoogleMap>
)
}
}
我觉得这里有两个问题:
- 如何在两个 NextJS 页面之间传递数据?
- 为什么当
suggest
值更新时我的 link 没有更新?
有几种不同的方法可以在页面之间传递数据,但查询字符串参数可能是我会使用的方法。尽管如果可能的话我不会在查询字符串中使用描述。您可以使用 NextJS <Link />
component
但是,您似乎已经尝试过类似的操作,但 link 没有更新。原因在于 markers
数据的设置方式。您已将其设置为组件中的常量,它告诉 React 不要监视对此对象的更改。当 onFromSuggestSelect
触发时,它会更新对象属性,然后……什么也不会。 React 认为 <Link />
不会有任何变化,因为 Parent.
没有任何变化
这就是我们拥有 React State 的原因。如果您将 markers
const 更改为使用 useState
挂钩,您应该会发现已实现的 <link />
会在值更改时更新。
一句警告;如果您之前没有使用过 useState
挂钩,请仔细阅读文档,以便您了解如何正确实现它。
希望这能解决您的问题。
总结
我有一个简单的 next.js 应用程序,有两个页面,index.js 和 results.js。索引页面有两个位置自动完成字段,在用户从推荐位置的下拉列表中选择位置后,return 位置的地址和 LatLng。 return 编辑后,此数据将存储在索引页上名为 markers
的变量中。当用户单击索引页面上的 Get Results 按钮时,我试图将地址和 LatLng 数据传递到结果页面,以便所选位置可以显示为标记在地图上。
问题
我已经断断续续地尝试了大约一个星期,但我不知道如何实现我想要的。我觉得应该有一个超级简单的方法来做到这一点,但我就是想不通。我试过类似的东西:
- 在单击按钮时传递数据彻底的请求参数,但是 link 是在页面呈现时根据变量值生成的,而不是在更新变量时更新
- 将地图与位置自动完成放在同一页面上并尝试使用状态自动重新加载地图,这对我来说似乎根本不起作用
- 我也研究过 Redux,但这似乎太复杂了,无法简单地将 object/it 的数据从一个页面传递到另一个页面
我理想的解决方案是将数据从 indext 传递到结果的简单方法。可能还值得指出的是,我是 React/Next.js 的新手,所以我可能会以错误的方式处理所有这些问题,一旦它起作用,我还将添加一个 API调用以获取两个 LatLng 点之间的方向,这也将显示在结果页面的地图上。
代码
index.js(简体)
{/* Import used next and style objects */ }
import Head from 'next/head'
import styles from '../styles/Home.module.css'
{/* Import react-bootstrap */ }
import { Container, Row, Col } from 'react-bootstrap'
{/* Import geosuggest */ }
import Geosuggest from 'react-geosuggest'
{/* Import used components */ }
import NavigationBar from '../components/NavigationBar'
import Footer from '../components/Footer'
{/* Import and use runtime vars for Google API */ }
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
const GoogleApiUrl = `https://maps.googleapis.com/maps/api/js?key=${publicRuntimeConfig.MAPS_JAVASCRIPT_API_KEY}&libraries=places`
export default function Home() {
const markers = {
from: {description: "", lat: 0, lng: 0},
to: {description: "", lat: 0, lng: 0}
}
const onFromSuggestSelect = (suggest) => {
console.log("New FROM location selected: \"" + suggest.description + "\"");
markers.from.description = suggest.description
markers.from.lat = suggest.location.lat
markers.from.lng = suggest.location.lng
}
const onToSuggestSelect = (suggest) => {
console.log("New TO location selected: \"" + suggest.description + "\"");
markers.to.description = suggest.description
markers.to.lat = suggest.location.lat
markers.to.lng = suggest.location.lng
}
return (
<div>
<Head>
<title>MyApp</title>
<meta name="description" content="MyApp" />
<link rel="icon" href="/favicon.ico" />
<script src={GoogleApiUrl}></script>
</Head>
<NavigationBar/>
<div className={styles.container}>
<main>
<Container>
<Row className="text-center">
<Col md={1}></Col>
<Col md={5}><Geosuggest data-test-id="autocomplete-start-test" placeholder="From..." onSuggestSelect={onFromSuggestSelect} country="gb" minLength="3" /></Col>
<Col md={5}><Geosuggest data-test-id="autocomplete-end-test" placeholder="To..." onSuggestSelect={onToSuggestSelect} country="gb" minLength="3" /></Col>
<Col md={1}></Col>
</Row>
</Container>
</main>
<Footer/>
</div>
</div>
)
}
results.js(简体)
{/* Import used next and style objects */ }
import Head from 'next/head'
import styles from '../styles/Home.module.css'
{/* Import used react-bootstrap objects */ }
import { Container } from 'react-bootstrap'
{/* Import used components */ }
import NavigationBar from '../components/NavigationBar'
import Footer from '../components/Footer'
import Map from '../components/Map'
{/* Import and use runtime vars for Google API */ }
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
const GoogleApiUrl = `https://maps.googleapis.com/maps/api/js?key=${publicRuntimeConfig.MAPS_JAVASCRIPT_API_KEY}&libraries=places`
export default function Home() {
const markers = {
from: {description: "", lat: 0, lng: 0},
to: {description: "", lat: 0, lng: 0}
}
return (
<div>
<Head>
<title>MyApp</title>
<meta name="description" content="MyApp" />
<link rel="icon" href="/favicon.ico" />
<script src={GoogleApiUrl}></script>
</Head>
<NavigationBar/>
<div className={styles.container}>
<main>
<Container>
{/* MARKERS NEEDS TO BE PASSED IN ON THE LINE BELOW */}
<Map markers={markers}/>
</Container>
</main>
</div>
<Footer/>
</div>
)
}
Map.js(分量)
import React from "react"
import { GoogleMap, Marker } from "@react-google-maps/api"
export default class Map extends React.Component {
render() {
// Set the map to fill its container
const containerStyle = { width: '500px', height: '500px' }
// Set the map to show the entire UK on initial load
const center = { lat: 54.476422, lng: -3.397340 }
const zoom = 6
// Return the map with the above defaults
return(
<GoogleMap mapContainerStyle={containerStyle} center={center} zoom={zoom}>
<Marker position={{ lat: this.props.markers.from.lat, lng: this.props.markers.from.lng }} />
<Marker position={{ lat: this.props.markers.to.lat, lng: this.props.markers.to.lng }} />
</GoogleMap>
)
}
}
我觉得这里有两个问题:
- 如何在两个 NextJS 页面之间传递数据?
- 为什么当
suggest
值更新时我的 link 没有更新?
有几种不同的方法可以在页面之间传递数据,但查询字符串参数可能是我会使用的方法。尽管如果可能的话我不会在查询字符串中使用描述。您可以使用 NextJS <Link />
component
但是,您似乎已经尝试过类似的操作,但 link 没有更新。原因在于 markers
数据的设置方式。您已将其设置为组件中的常量,它告诉 React 不要监视对此对象的更改。当 onFromSuggestSelect
触发时,它会更新对象属性,然后……什么也不会。 React 认为 <Link />
不会有任何变化,因为 Parent.
这就是我们拥有 React State 的原因。如果您将 markers
const 更改为使用 useState
挂钩,您应该会发现已实现的 <link />
会在值更改时更新。
一句警告;如果您之前没有使用过 useState
挂钩,请仔细阅读文档,以便您了解如何正确实现它。
希望这能解决您的问题。