簡體   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