[英]React: How to properly update state of parent component after changing child component
I'm new to React and was wondering if I could get some advice here.我是 React 的新手,想知道是否可以在这里得到一些建议。
I currently am using Mapbox and have map coordinates set to Manhattan along with a description about the city.我目前正在使用 Mapbox,并将 map 坐标设置为曼哈顿以及有关城市的描述。 I would like the descriptions and the location of the map to change every time a user presses a button (eg the map would move to Brooklyn upon the user clicking)
我希望每次用户按下按钮时 map 的描述和位置都会改变(例如,用户点击后 map 将移动到布鲁克林)
Essentially, I am trying to build this: https://docs.mapbox.com/mapbox-gl-js/example/playback-locations/ , but where the neighborhoods slide over only to button clicks.从本质上讲,我正在尝试构建这个: https://docs.mapbox.com/mapbox-gl-js/example/playback-locations/ ,但社区只滑动到按钮点击。 I wasn't sure how I could move this vanilla Javascript and html into React, so I tried to recreate the best I can.
我不确定如何将这个普通的 Javascript 和 html 移动到 React 中,所以我尝试尽可能地重新创建。
My code is as follows.我的代码如下。 I'm aware that the child is a class component and the parent is a function component.
我知道子组件是 class 组件,父组件是 function 组件。
Parent Component父组件
const locations = [
{
'id': '1',
'title': 'Manhattan',
'description': 'The capital of culture, finance, entertainment, and fashion. Need we say more?',
'camera': {center: [-74.007, 40.7437], bearing: 25.3, zoom: 11.5}
},
{
'id': '2',
'title': 'Bronx',
'description': "A fantastic zoo and botanical garden. Not to mention the birthplace of hip-hop!",
'camera': {center: [-73.8709, 40.8255], bearing: 0, zoom: 12.21}
},
{
'id': '3',
'title': 'Brooklyn',
'description': "This borough is experiencing a renaissance and continues to bring new surprises.",
'camera': {center: [-73.9499, 40.626], bearing: -8.9, zoom: 11.68}
},
{
'id': '4',
'title': 'Queens',
'description': "Experience one of the world's most diverse places!",
'camera': {center: [-73.8432, 40.6923], bearing: 36, zoom: 11.37}
},
{
'id': '5',
'title': 'Staten Island',
'description': 'A great place for family and friends with a stunning view, tons of parks, and a free ferry ride!',
'camera': {center: [-74.1991, 40.5441], bearing: 28.4, zoom: 11.64}
},
{
'title': 'Five Boroughs of New York',
'description': 'New York City is made up of five boroughs: Bronx, Brooklyn, Manhattan, Queens and Staten Island. Each one has its own attractions-not to mention data!',
'camera': {center: [-74.0315, 40.6989], zoom: 9.68, bearing: 0, pitch: 0}
}
];
function Neighborhood() {
const [count, setCount] = useState(0);
const borough = <Boroughs data={locations[count]}/>
const [map, setMap] = useState(borough);
function increase() {
setCount(count+1);
setMap(<Boroughs data={locations[count]}/>);
}
function decrease() {
setCount(count-1);
setMap(<Boroughs data={locations[count]}/>);
}
return (
<div className="all-neighborhoods">
<PageNavbar active="Listing" />
<header className="App-header">
</header>
{count}
<button onClick={decrease}>-</button>
<button onClick={increase}>+</button>
<div className="container-fluid">
<div className="row d-flex flex-fill min-vh-100">
{map}
</div>
</div>
</div>
);
}
export default Neighborhood;
Child Component子组件
mapboxgl.workerClass = MapboxWorker;
mapboxgl.accessToken = '<hidden>';
export default class Boroughs extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
title: this.props.data.title,
description: this.props.data.description,
lat: this.props.data.camera.center[0],
long: this.props.data.camera.center[1],
zoom: this.props.data.camera.zoom,
bearing: this.props.data.camera.bearing
}
this.mapContainer = React.createRef();
}
componentDidMount() {
const { lat, long, zoom, bearing } = this.state;
const map = new mapboxgl.Map({
container: this.mapContainer.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [parseFloat(lat), parseFloat(long)],
maxZoom: 16,
minZoom: 9,
zoom: parseFloat(zoom),
bearing: parseFloat(bearing),
pitch: 50
});
}
render() {
const { title, description } = this.state;
return (
<div ref={this.mapContainer} className="map-container flex-grow-1">
<div className="map-overlay-container">
<div className="map-overlay">
<h2 id="location-title">{title}</h2>
<p id="location-description">{description}</p>
</div>
</div>
</div>
);
}
}
Try reading up on the React Context API .尝试阅读React 上下文 API 。 Anything that is wrapped within the context provider will be exposed to the states of the context
包含在上下文提供程序中的任何内容都将暴露给上下文的状态
It's not advisable for the child to change the state of the parent component.不建议孩子更改父组件的state。 There is this hack though, Add a function in the parent that updates the state, pass it to the child as a prop and call it every time a change happens in the child component.
但是有这个 hack,在更新 state 的父级中添加一个 function,将其作为道具传递给子级,并在每次子组件发生更改时调用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.