我有3个具有这种关系的React组件:
单击以更新ChildofChild
组件中的状态时,我想在Parent
组件中有一个按钮。我可以通过道具将其发送到Child
组件,并在其中运行功能。
ChildOfChild
// ChildOfChild Component
export class PlaceInfoWindow extends Component {
render() {
const {description, name, price} = this.props
return(
<InfoWindow onCloseClick={this.props.closeWindow}>
<div>
<h1>{name}</h1>
<p>{description}</p>
<span>${price}</span>
<button type="button" onClick={this.props.onAdd} className="btn btn-primary btn-success m-2">Add</button>
</div>
</InfoWindow>
);
}
}
export default PlaceInfoWindow
孩子
//Child Component
export class PlaceMarker extends Component {
constructor(props) {
super(props);
this.state = {
showTooltip: false,
};
}
clickTooltip() {
this.setState({ showTooltip: !this.state.showTooltip });
}
closeWindow() {
this.setState({ showTooltip: false });
}
render() {
const { showTooltip } = this.state;
const { lat, lng, name, price, description } = this.props;
return (
<Marker
position={{
lat: parseFloat(lat),
lng: parseFloat(lng)
}}
onClick={this.clickTooltip.bind(this)}
icon="https://image.ibb.co/cGPSW8/red_marker.png"
>
{showTooltip && (
<PlaceInfoWindow
description={description}
name={name}
price={price}
closeWindow={this.closeWindow.bind(this)}
onAdd={this.props.onAdd}
/>
)}
</Marker>
);
}
}
export default PlaceMarker;
父母
// Parent Component
const AirbnbMap = withGoogleMap(props => (
<GoogleMap
defaultCenter={props.center}
defaultZoom={props.zoom}
defaultOptions={{
styles: userMapStyle
}}
>
{props.places.length > 0 &&
props.places.map(place => (
<PlaceMarker
key={`place${place.id}`}
id={place.id}
lat={place.latitude}
lng={place.longitude}
description={place.description}
name={place.name}
price={place.price}
onAdd={this.handleAdd}
/>
))}
</GoogleMap>
));
export class Map extends Component {
constructor(props) {
super(props);
this.zoom = 7;
this.state = {
lat: 50.0515918,
lng: 19.9357531,
places: [
{
id: 1,
latitude: 50,
longitude: 20,
description: "ABC",
name: "City",
price: 20
}]
};
}
handleAdd = () => {
console.log("handle add called");
};
render() {
const { lat, lng, places } = this.state;
console.log(places);
return (
<div style={{ width: `100%`, height: `750px` }}>
<AirbnbMap
center={{
lat: lat,
lng: lng
}}
places={places}
zoom={this.zoom}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;
但是如何将其发送到Parent
(两个级别)组件?这样,Child
组件将仅将道具从其子对象(Parent
获取的ChildofChild
组件转发。
答案 0 :(得分:2)
仅转发道具没有问题。这包括处理程序:
class Parent extends Component {
handle = event => { /* handle event */ };
render() {
return (
<Child handler={this.handle} />
);
}
}
const Child = ({handler}) => (
<ChildOfChild handler={handler} />
);
const ChildOfChild = ({handler}) => (
<button onClick={handler}>Click me!</button>
);
答案 1 :(得分:0)
您的顶级Parent组件不是AirbnbMap,而是Map类。另外,您在Map类中声明了handleAdd,但没有将其传递给Airbnb组件。在地图上,您应该将其传递给:
{
"comments": {
"5a6efb94b0e8c36f99fba019": {
"id": "5a6efb94b0e8c36f99fba019",
"message": "Alias quod est voluptatibus aut quis sunt aut numquam."
},
"5a6efb94b0e8c36f99fba01b": {
"id": "5a6efb94b0e8c36f99fba01b",
"message": "Harum quia asperiores nemo."
},
"5a6efb94b0e8c36f99fba01c": {
"id": "5a6efb94b0e8c36f99fba01c",
"message": "Vel veniam consectetur laborum."
},
"5a6efb94b0e8c36f99fba01e": {
"id": "5a6efb94b0e8c36f99fba01e",
"message":
"Possimus beatae vero recusandae beatae quas ut commodi laboriosam."
}
},
"blogPosts": {
"5a6efb94b0e8c36f99fba016": {
"id": "5a6efb94b0e8c36f99fba016",
"title": "Dolorem voluptatem molestiae",
"comments": [
"5a6efb94b0e8c36f99fba019",
"5a6efb94b0e8c36f99fba01b",
"5a6efb94b0e8c36f99fba01c",
"5a6efb94b0e8c36f99fba01e"
]
}
},
"users": {
"5a6efb94b0e8c36f99fba013": {
"id": "5a6efb94b0e8c36f99fba013",
"email": "Lloyd.Nikolaus@yahoo.com",
"posts": ["5a6efb94b0e8c36f99fba016"]
}
}
}
然后在AirbnbMap类上:
<AirbnbMap handleAdd={this.handleAdd}
// Rest of props here
/>
其余的看起来还可以。
答案 2 :(得分:0)
从React 16.3开始,您可以使用新的Context API,因此您无需将道具传递给每个孩子,并且可以轻松整洁地举起状态。
import React, { Component, createContext } from 'react';
const ParentContext = createContext({});
class Parent extends Component {
handle = event => { console.log('Event', event) };
render() {
return (
<ParentContext.Provider value={{
onClick: this.handle,
}}>
<Child />
</ParentContext.Provider>
);
}
}
const Child = () => (<ChildOfChild />);
const ChildOfChild = () => (
<ParentContext.Consumer>
{ (context) => <button onClick={context.onClick}>Click me!</button>}
</ParentContext.Consumer>
);
export default Parent;