繁体   English   中英

React.js:从另一个组件调用函数?

[英]React.js: Call functions from another component?

我是 React.js 的新手,对链接不同组件中的两个函数感到困惑。

我正在尝试实现两个组件之间的通信。 React-leaflet 对我来说相当困难,所以我使用一种丑陋的方式来实现下面的目标:

所以,这是我的父组件,里面有一个表,它有一个 'handleOnRowSelected' function。我希望我的另一个组件(它是一个地图)有一个 function,所以当用户点击 map 组件时,表组件也将触发 'handleOnRowSelected' function。

如果你能帮助我,非常感谢!

class Pd extends Component {

    state = {  
        counties:[],
        allCountyTotal:0,
        service:[],
        selectedCounties:[],
    };

    url = 'https://raw.githubusercontent.com/magluie/mappd/master/agegender.csv';

    async componentDidMount () {
        const response = await axios.get(this.url);
        const rows = response.data.split("\n");
        console.log(rows[0].split(","));

        const counties = [];
        const service = [];


        let allCountyTotal = 0;

        for( let i = 1; i < rows.length; i++) {
            const row = rows[i].split(",");
            const countyName = row[0];
            const atwenty = Number(row[1]);
            const athirty = Number(row[2]);
            const afourty = Number(row[3]);
            const afifty1 = Number(row[4]);
            const afifty2 = Number(row[5]);
            const asixty1 = Number(row[6]);
            const asixty2 = Number(row[7]);
            const aseventy1 = Number(row[8]);
            const aseventy2 = Number(row[9]);
            const aeighty1 = Number(row[10]);
            const aeighty2 = Number(row[11]);
            const malenum = Number(row[12]);
            const femalenum = Number(row[13]);
            const total = Number(row[14]);
            const serviceName = row[15]
       

            if(countyName !== "" && serviceName !== "") {
               
                counties.push({
                    name:countyName,
                    total: total,
                    female: femalenum,
                    male: malenum,
                    twenty: atwenty,
                    thirty: athirty,
                    fourty: afourty,
                    fifty1: afifty1,
                    fifty2: afifty2,
                    sixty1: asixty1,
                    sixty2: asixty2,
                    seventy1:aseventy1,
                    seventy2: aseventy2,
                    eighty1: aeighty1,
                    eighty2:aeighty2,
                
                    service: serviceName,

                });
            }

        }

     
        this.setState({
            counties:counties,
            allCountyTotal:allCountyTotal,
            service:service,
        });
    }

   
    handleOnRowSelected =(countyToUpdate) =>{
        const counties =[...this.state.counties];
        const countyIndex = counties.findIndex(
            (c) => c.name === countyToUpdate.name,
            (c) => c.female === countyToUpdate.female,
            (c) => c.male === countyToUpdate.male,
            (c) => c.twenty=== countyToUpdate.twenty,
            (c) => c.thirty === countyToUpdate.thirty,
            (c) => c.fourty === countyToUpdate.fourty,
            (c) => c.fifty1 === countyToUpdate.fifty1,
            (c) => c.fifty2 === countyToUpdate.fifty2,
            (c) => c.sixty1 === countyToUpdate.sixty1,
            (c) => c.sixty2 === countyToUpdate.sixty2,
            (c) => c.seventy1 === countyToUpdate.seventy1,
            (c) => c.seventy2 === countyToUpdate.seventy2,
            (c) => c.eighty1 === countyToUpdate.eighty1,
            (c) => c.eighty2 === countyToUpdate.eighty2,
        );
        const county = {
            name: countyToUpdate.name,
            total: countyToUpdate.total,
            service: countyToUpdate.service,
            female: countyToUpdate.female,
            male: countyToUpdate.male,
            twenty: countyToUpdate.twenty,
            thirty: countyToUpdate.thirty,
            fourty: countyToUpdate.fourty,
            fifty1: countyToUpdate.fifty1,
            fifty2: countyToUpdate.fifty2,
            sixty1: countyToUpdate.sixty1,
            sixty2: countyToUpdate.sixty2,
            seventy1:countyToUpdate.seventy1,
            seventy2: countyToUpdate.seventy2,
            eighty1: countyToUpdate.eighty1,
            eighty2:countyToUpdate.eighty2,

            //get the oppisit value
            selected: !countyToUpdate.selected,
        };
       
        
        counties[countyIndex] = county;
        this.setState({counties, selectedCounties: counties.filter((c) =>c.selected),
        });
    };

    sortByTotal =(countyA, countyB) =>{
        if(countyB.total > countyA.total) return 1;
        else if (countyB.total <countyA.total) return -1;
        else return 0;
    };

    handleOnSortByTotal = (event) =>{
        this.handleOnSort(event, this.sortByTotal);
    };

    sortByCountyName =(countyA, countyB) =>{
        if(countyA.name > countyB.name) return 1;
        else if (countyA.name <countyB.name) return -1;
        else return 0;
    };

    handleOnSortByCountyName = (event) =>{
       this.handleOnSort(event, this.sortByCountyName);
    };

    handleOnSort = (event,sortBy) =>{
        event.preventDefault();
        const counties = [...this.state.counties]
        counties.sort(sortBy);

        this.setState({counties});

    };


    render() {
        const { counties, allCountyTotal, selectedCounties}=this.state;

        return (           
            <div>
            <MyMap />

                    <CountyTable 
                counties = {counties} 
                onSortByTotal = {this.handleOnSortByTotal} 
                onSortByCountyName = {this.handleOnSortByCountyName} 
                onRowSelected = {this.handleOnRowSelected}
                
                /> 
    
            </div>
        );
    }
}

export default Pd;

这是 Map 组件:

const DEFAULT_LONGITUDE = 51.903614;
const DEFAULT_LATITUDE = -8.468399;



const mapstyle = {
    height: '600px',
    width: '500px',
    background:0,
    marginLeft: '50%',
    marginTop: '3%',
    marginBottom: '0.005%'
};

const contystyle = {
    fillColor:'darkgreen',
    weight: 2,
    opacity: 1,
    color: 'white',
    dashArray: '3',
    fillOpacity: 0.7
}




class  MyMap extends React.Component{
    constructor(){
        super()
        this.callHandleOnRowSelected = this.callHandleOnRowSelected.bind(this);
        this.handleOnRowSelected = this.handleOnRowSelected.bind(this);
    }

    callHandleOnRowSelected = () => {
        this.handleOnRowSelected()
    };

    //functions for map
    highLightCounty = (event) =>{
        event.target.setStyle({
            weight:5,
            color:'white',
            fillColor:'yellow',
            fillOpacity:0.6
         });
    };
    //resethighlight county style
    resetCountyColor = (event) => {
        event.target.setStyle({
            fillColor:'darkgreen',
            weight: 2,
            opacity: 1,
            color: 'white',
            dashArray: '3',
            fillOpacity: 0.7
        });
    };

    // callHandleOnRowSelected = (event) =>{
    //     this.handleOnRowSelected()
    // };
    
    // functions for features of the map
    onEachCountry = (country, layer) => {
    const countryName = country.properties.NAME_TAG;
    console.log(countryName);
    layer.bindPopup(countryName);

    layer.on({
        mouseover: this.highLightCounty,
        mouseout: this.resetCountyColor,
        click: this.callHandleOnRowSelected,
      
        });
    };
    
    
    

    render() {
        const Component = ({func}) => {
            handleOnRowSelected () 
        };


        return (
            <div>

                <Map style={mapstyle} 
                zoom = {6.5} 
                center={[latitude, longitude]}
                maxZoom={10}
                attributionControl={true}
                zoomControl={true}
                doubleClickZoom={true}
                scrollWheelZoom={true}
                dragging={true}
                animate={true}
                easeLinearity={0.35}>
                    
                    <GeoJSON 
                style={contystyle} 
                data = {mapData.features}
                onEachFeature = {this.onEachCounty} 
                />

                </Map>

        </div>
        );
    }

}

 

如果您使用的是 redux,您可以考虑使用 redux thunk 或 redux saga。 如果不是,请考虑使用 redux。redux 的开发人员还提供了 redux 工具包,可以为您完成连接 redux、react-redux 和 redux-thunk 的艰苦工作。

Redux React Redux Redux 工具包Redux Thunk Redux Saga

解释原因:

我相信你的问题是关于 state 管理。 当源组件的 state 发生变化时,您需要在目标组件中发生 function(这会更改目标组件的 state)。

在这种情况下,您应该通过父组件连接所有状态(将 state 向上移动),并通过 props 提供父组件的功能。

这个问题很常见,并且经常会在你的反应组件的其他部分发现。

The state part of the problem is solved by introducing redux. The function part of the problem is partially solved by redux if the function simply changes state, and the rest solved by introducing redux saga or redux thunk.

将您的父方法作为子组件的道具传递。 您的 Map 组件应该将道具作为构造函数的一部分,然后通过获取道具传递的 function 在子组件上调用您的 function。

// 父组件.jsx

  // something here ...
  render() {
    return (
      <div><ChildComponent onClick={this.onWhatever} /></div>
    )
  }

// 子组件.jsx

class ChildComponent extends React.Component {
  constructor(props) {
    super(props);
      his.onSomething = this.onSomething.bind(this);
  }
      
  onSomething = () => {
    const {onClick} = this.props;
    onClick();
  }
  // other things here ...
}

我建议使用 React Hooks,因为您的子组件无论如何都会返回一个功能组件。 除非您对 React 有适当的了解,否则我不会费心处理 Redux(即使当您为多项事情共享 state 时它是一个不错的选择)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM