2017-07-27 45 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

相关问题