我目前正试图围绕如何构建ReactJS应用程序。以下是相关信息:
开发环境:npm,webpack
依赖关系:React,ReactDOM,React路由器,React路由器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
和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 :(得分:0)
当您使用导入/导出时,模块之间不会共享全局变量。这是一件好事,但您可以从模块中导出多个变量。例如,您可以在App.js中export locationDataArray;
从其他模块访问它,而不会破坏该模块的现有导出和导入。话虽如此,你几乎从不想在React中分享全局数据。作为一般经验法则,您应该将组件所依赖的数据“提升”到需要的树中的最高组件(如果您愿意,您甚至可以创建额外的父组件以使此组合更容易)。
当子组件依赖于来自父组件数据的部分数据时,通常应该通过props从父组件传递数据子集。使用给定location
的实际地图数据向MapHolder
添加id
道具,而不是让组件查找id
本身。然后在MapHolder
的父级中,将其渲染为:
<MapHolder
location={locationDataArray.locations.find(location => location.slug === ID)}
/>
答案 1 :(得分:-1)
您正在寻找的是React's Context功能。它非常低级,是一个不稳定的API,可能在任何时候发生变化。含义:谨慎使用。
在某些情况下,您希望通过组件树传递数据,而不必在每个级别手动传递道具。您可以使用强大的&#34; context&#34;直接在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
}
}
如果觉得笨拙,那是因为它的意思是:
绝大多数应用程序不需要使用上下文。
如果您希望应用程序稳定,请不要使用上下文。它是一个实验性的API,很可能会在未来的React版本中破解。