如何设置上下文中同级组件的状态



我想用onClick设置同级组件的State。兄弟姐妹组件是map.js中的KarttaSidebar.js边栏。我在Kartta索按钮从边栏调用该函数。我试着用上下文和道具来做这件事,但我失败了。有更好的方法吗?我刚反应过来,我真的很感激你的帮助。谢谢

index.js(父级(

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './css/main.css';
import 'bootstrap/dist/js/bootstrap.bundle.js';
import 'leaflet/dist/leaflet.css';
import { Kartta } from './components/map';
import Sidebar from './components/sidebar';
import Navbar from './components/navbar';
class App extends Component {
constructor(props) {
super(props);
}
componentDidMount = () => {
}
render() {
console.log(this.state);
return (
<div id="main-container" className="container-fluid h-100 p-0">
<Navbar />
<div id="container0" className="row h-100 w-100 m-0 wrapper">
<Sidebar />
<div id="container02" className="col h-100 w-100 p-0">
<Kartta />
</div>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));

map.js(同级1(

import React, { Component, createContext } from 'react';
import L from 'leaflet';
import { Map, Marker, Popup, TileLayer } from 'react-leaflet';
const position = [62.241581, 25.758742];
export const MapContext = createContext();
export class Kartta extends Component {
constructor(props) {
super(props);
this.state = {
places: []
};
this.fetchAll = this.fetchAll.bind(this);
}
componentDidMount() {
}
fetchAll = () => {
console.log("täällä");
fetch('test.json')
.then(res => res.json())
.then((data) => {
this.setState({ places: data })
})
.catch(console.log(this.state.places))
}
iconSize = (iconName) => {
if (iconName == 'tree.png') {
return 30, 30
}
else {
return 15, 30
}
}
MapComponent = () => {
if(this.state.places.length > 0){
return (
<Map center={position} zoom={7}>
<button onClick={this.haeKaikki}>Hae</button>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="&copy; <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
/>
{this.state.kohteet.map((kohde) => (
<Marker key={'key' + kohde.id} position={[kohde.lon, kohde.lat]} icon={
new L.Icon({
iconUrl: require('../img/' + kohde.icon),
iconSize: new L.Point(this.iconSize(kohde.icon)),
id: kohde.id + kohde.icon
})
}>
<Popup>
<h1>{kohde.name}</h1>
<p>{kohde.desc}</p>
</Popup>
</Marker>
))}
</Map>
)
}
else {
return (
<Map center={position} zoom={7}>
<button onClick={this.haeKaikki}>Hae</button>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="&copy; <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
/>
</Map>
)
}
}
render() {
return (
<MapContext.Provider value = {{
state: this.state,
update: this.fetchAll
}}>
<div id="mapid" className="h-100 w-100">
<this.MapComponent />
</div>
</MapContext.Provider>
)
}
}
export const MapConsumer = MapContext.Consumer;

sidebar.js(同级2(

import React, { Component } from 'react';
import { MapConsumer } from './map';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
class Sidebar extends Component {
constructor(props) {
super(props);
this.state = {
kohteet: []
};
}
componentDidMount = () => {
}
handleClick = (e) => {
e.preventDefault();
}
render() {
return (
<div className="p-2 collapse in" id="sidebar">
<div className="list-group panel" id="sidebar-div0">
<form id="sidebar-form0">
<div id="sidebar-div01" className="form-group active">
<label id="sidebar-label0" htmlFor="exampleInputEmail1">Kohteen nimi</label><span> </span>
<FontAwesomeIcon icon={faInfoCircle} className="pointer dropdown-toggle" data-toggle="dropdown" alt="Hakuohjeet" />
<div id="search-info" className="p-2 dropdown-menu dropdown-menu-right">
<p>Hae kirjoittamalla tägejä</p>
</div>
<div className="row">
<div className="col-7 ml-3 p-0">
<input type="text" className="form-control" id="searchByName" aria-describedby="emailHelp" placeholder="Syötä kohteen nimi" />
</div>
<button id="sidebar-button0" type="submit" className="btn btn-primary ml-2 col-3" onClick={this.handleClick}>Search</button>
</div>
</div>
</form>
<div id="sidebar-div02" className="dropdown">
<a id="sidebar-button1" className="btn btn-light dropdown-toggle p-0 thaku" type="button" data-toggle="dropdown">Tarkennettu haku
<span id="sidebar-span0" className="caret"></span></a>
<div id="sidebar-div020" className="p-0 dropdown-menu border-0 mt-2 w-100 h-100">
<form id="sidebar-form1">
<div id="sidebar-div0200" className="form-group p-0">
<label id="sidebar-label1" htmlFor="exampleInputEmail1">Paikkakunta</label>
<input id="sidebar-input1" type="text" className="form-control" placeholder="Syötä paikkakunta" />
</div>
<div id="ch-div0" className="row pl-3">
<label id="lbl-location">Sijainti</label>
<input id="ch-location" className="mt-2 ml-2" type="checkbox" aria-label="Checkbox for following text input" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<label className="input-group-text" htmlFor="inputGroupSelect01">Palvelut</label>
</div>
<select className="custom-select" id="inputGroupSelect01">
<option defaultValue>Valitse...</option>
<option value="1">Kakkapaikka</option>
<option value="2">Pissapaikka</option>
<option value="3">Kaljapaikka</option>
</select>
</div>
<div id="dropdown-div3" className="row p-0">
<button id="sidebar-dropdown-button0" type="submit" className="ml-3 btn btn-primary">Tarkennettu haku</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
export default Sidebar;

如果你想对同级组件产生一些影响,有一些解决方案:

  1. 使用Redux-

  2. 通过props将值传递给Parent,然后更改Parent的状态,然后将值从Parent状态传递给同级组件。如:Child1元素->Parent->Child2元素。

父元素

class Parent extends Component {
constructor(props) {
super(props);
this.state={
valueToChild2:null
}
}
getValueFromChild1=(value)=>{
if(this.state.valueToChild2 !== value)
{
this.setState({
valueToChild2:value
})
}
}
render() {
return (
<div>
<Child1 getValueFromChild1={this.getValueFromChild1} />
<Child2 passValueToChild2={this.state.valueToChild2}/>
</div>
);
}
}

Child1元素:

class Child1 extends Component {
constructor(props) {
super(props);
}
sendValueToParent=()=>{
let msg="Hello"
this.props.getValueFromChild1(msg)
}
render() {
return (
<div onClick={this.sendValueToParent}>
</div>
);
}
}

Child2元素:

class Child2 extends Component {
constructor(props) {
super(props);
this.state={
value:null
}
}
componentDidMount(){
if(this.props.passValueToChild2)
{
this.setState({
value:this.props.passValueToChild2
})
}
}
componentDidUpdate(){
if(this.props.passValueToChild2)
{ 
if(this.props.passValueToChild2 !== this.state.value)
{
this.setState({
value:this.props.passValueToChild2
})
}
}       
}
render() {
return (
<div>
</div>
);
}
}

最新更新