2017-07-27 80 views
1

我目前正試圖圍繞如何構建一個ReactJS應用程序。以下是相關信息:我如何製作它,以便props.match.params.id可以訪問任何子組件?

開發環境:NPM,的WebPack

依賴:反應,ReactDOM,陣營路由器,陣營路由器DOM

代碼:(清理了一下,以不透露更多敏感信息)

/*********** 
TABLE OF CONTENTS 
01.0.0 - Imports 
02.0.0 - Data 
03.0.0 - Components 
03.1.0 -- Base 
03.2.0 -- Location 
03.3.0 -- Main 
03.3.2 --- Map 
04.0.0 - Render 
***********/ 

/* 01.0 Imports */ 
import React from 'react'; 
import ReactDOM from 'react-dom'; 
import $ from 'jquery'; 
import { 
    HashRouter, 
    Route, 
    Switch, 
    Link 
} from 'react-router-dom'; 

console.log("Set-up successful"); 
/* 02.0 Data */ 
const locationDataArray = { 
    locations: [ 
    { 
     "location": "Scenario A", 
     "slug": "lipsum", 
     "googleUrl": "https://www.google.com/maps/place/Central+Park/@40.7828687,-73.9675438,17z/data=!3m1!4b1!4m5!3m4!1s0x89c2589a018531e3:0xb9df1f7387a94119!8m2!3d40.7828647!4d-73.9653551", 
     "mapUrl": "locations/scenA/main-map.png", 
     "areaMaps": [ 
     { 
      "name": "Overall", 
      "url": "inner/map-overall.html" 
     }, { 
      "name": "A", 
      "url": "inner/map-a.html" 
     }, { 
      "name": "B", 
      "url": "inner/map-b.html" 
     } 
     ], 
     "overallPDF": "diagram.pdf", 
     "mapKey": "mapkey.txt", 
     "mapImagemap": "imagemap.txt" 
    } // list truncated for your convenience. 
    ], 
    all: function() {return this.locations}, 
    get: function(id) { 
    const isLocation = q => q.slug === id 
    return this.locations.find(isLocation) 
    } 
} 

/* 03.0 Components */ 
/* 03.1 Base */ 
class App extends React.Component { 
    constructor() { 
    super(); 
    console.log("<App /> constructor locationDataArray: " + locationDataArray); 
    this.state = { 
     locationData: locationDataArray, 
     test: 'testing!' 
    }; 
    } 
    render() { 
    console.log("<App /> locationDataArray: " + locationDataArray); 
    console.log("<App /> state, testing: " + this.state.test); 
    return(
     <div> 
     <Switch> 
      <Route exact path='/' component={LocationGrid} /> 
      <Route path='/locations/:id' component={MainMap}/> 
     </Switch> 
     </div> 
    ); 
    } 
} 

/* 03.2.0 -- Location */ 

class LocationGrid extends React.Component { 
    constructor() { 
    super(); 
    } 
    render() { 
    return(
     <div> 
     <h2>Location Grid</h2> 
     <div> 
      <Link to="/locations">Main Map</Link> 
     </div> 
     <div> 
      <ul> 
      { // this part works with extra items in locationDataArray. 
       locationDataArray.all().map(q => (
       <li key={q.slug}> 
        <Link to={`locations/${q.slug}`}>{q.location}</Link> 
       </li> 
      )) 
      } 
      </ul> 
     </div> 
     </div> 
    ); 
    } 
} 

/* 03.3.0 -- Main */ 

class MainMap extends React.Component { 
    constructor(props) { 
    super(); 
    console.log("Main map is on"); 
    const location = locationDataArray.get(
     props.match.params.id 
    ); 
    if (!location) { 
     console.log("No such location!"); 
    } 
    if (location) { 
     console.log("These tests show that the locationDataArray is accessible from this component."); 
     console.log("A: props.match.params.id is: " + props.match.params.id); 
     console.log("B: Location is: " + location.location); 
     console.log("C: Map URL: " + location.mapUrl); 
     console.log("State is: " + location); 
    } 
    } 
    render() { 
    return (
     <div> 
     <MapHolder /> 
     </div> 
    ); 
    } 
} 

/* 03.3.2 --- Map */ 
//var mapUrl = require(location.mapUrl); 
class MapHolder extends React.Component { 
    render() { 
    console.log("And these tests show that the locationDataArray is NOT accessible from this component."); 
    console.log("1. Map location test, mapUrl: " + location.mapUrl); 
    console.log("2. Map location test, slug: " + location.slug); 
    return <div> 
     <img id="imagemap" className="map active" src={location.mapUrl} width="1145" height="958" useMap="#samplemap" alt="" /> 
     <map name="samplemap" id="mapofimage"> 
     <area target="" alt="1" title="1" href="inner/01.html" coords="288,356,320,344,347,403,315,420" shape="poly"></area> 
     {/* Additional imagemap areas. Truncated for your conveinence.*/} 
     </map> 
     <p>A map would be here if I could figure out the bug.</p> 
     </div> 
    } 
} 

/* 04.0.0 -- Render */ 

ReactDOM.render((
    <HashRouter> 
    <App /> 
    </HashRouter> 
), document.getElementById('container')); 

package.json and webpack.config.js都在git repository,如果需要。

總體目標:我想通過React Router路由參數和JSON對象向主要組件和子組件動態提供信息。實質上,我希望能夠將param與對象中的項目關聯起來,以便組件可以引用諸如arrayItem.itemProperty之類的東西,並且它可以動態工作。

我想盡可能地遠離Redux,因爲我現在已經略微被React淹沒了。

當前的問題

的陣列(在線路26-55)是在的代碼,但1個組分(<MainMap />,線113-138)的以外的任何東西就不能訪問它。

其中一個子組件的示例爲<MapHolder />,位於第142-156行。 (在這些情況下,我得到ReferenceError: props is not defined)。

我該如何使props.match.params.id(或任何其他能使這項工作的東西)可以訪問任何子組件?我很清楚代碼並不完美,但這仍然處於早期生產階段,所以我想解決這個問題,希望剩下的問題能夠解決。因此。)

回答

0

當您使用導入/導出時,全局變量不在模塊之間共享。這是一件好事,但您可以從模塊中導出多個變量。例如,您可以在您的App.js中使用export locationDataArray;從其他模塊訪問它,而不會中斷該模塊的現有導出和導入。這就是說你幾乎從不想像這樣在React中共享全局數據。作爲一般的經驗法則,您應該將組件依賴的數據「提升」到需要的樹中的最高組件(如果需要,您甚至可以使用額外的父組件來使該組合更容易)。

當子組件依賴來自父組件的部分數據的數據時,通常應通過道具傳遞父組件的數據子集。添加location道具到MapHolder與給定id的實際地圖數據,而不是使組件查找id本身。然後在MapHolder的父,使它像這樣:

<MapHolder 
    location={locationDataArray.locations.find(location => location.slug === ID)} 
    /> 
-1

你在找什麼是React's Context功能。這是相當低級的,並且是一個不穩定的API,可能隨時會改變。含義:謹慎使用。

在某些情況下,您希望通過組件樹傳遞數據,而不必在每個級別手動傳遞道具。您可以直接在React中使用強大的「上下文」API執行此操作。

TL; DR:

首先,聲明你將作出便於兒童上下文對象的形狀,並實現getChildChildContext實際上歸還:

class MyComponent extends React.Component { 
    ... 
    static childContextTypes = { 
    foo: PropTypes.string // or whatever you have 
    }; 

    getChildContext() { 
    return {foo: "some value"}; 
    } 
    ... 
} 

然後,當你想要訪問子組件中的上下文,聲明您希望通過在子組件上聲明contextTypes來實現:

class SomeChildComponent extends React.Component { 
    static childContextTypes = { 
    foo: PropTypes.string 
    }; 

    render() { 
    // use in your component by accessing this.context.foo 
    } 
} 

如果感覺klunky,這是因爲它的意思是:

絕大多數的應用程序並不需要使用情境。

如果您希望您的應用程序穩定,請勿使用上下文。這是一個實驗性的API,它很可能在未來的React版本中被打破。

你可能會得到來自使用狀態管理庫,如reduxmobx管理國家,應該是從任意組件訪問更好的結果。

+0

我不同意,我認爲這將是更好的數據子集傳遞到子組件的道具。上下文是一種破解,你不一定需要使用redux或mobx來實現這樣的事情(儘管它們可以幫助很多,取決於情況)。 –

+0

我實際上同意你的觀點,我特意回答標題中提出的問題。 – rossipedia

相關問題