代码之家  ›  专栏  ›  技术社区  ›  Emily Serven

我如何使其成为props.match.params。id是否可以访问任何子组件?

  •  1
  • Emily Serven  · 技术社区  · 8 年前

    我目前正努力研究如何构造ReactJS应用程序。以下是相关信息:

    :npm,网页包

    :React,ReactDOM,React Router,React Router 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 route param和JSON对象动态地向主组件和子组件提供信息。本质上,我希望能够将param与对象中的一个项相关联,这样组件就可以引用类似的内容 arrayItem.itemProperty 它可以动态工作。

    :

    数组(第26-55行)在代码中,但在1个组件之外( <MainMap /> ,第113-138行)无法访问它。

    这些子组件之一的示例如下 <MapHolder /> ReferenceError: props is not defined 在这种情况下。)

    props.match.params.id

    ( 我很清楚代码并不完美。但这仍处于早期生产阶段,所以我只想解决这一个问题,希望其他问题会因此得到解决。)

    2 回复  |  直到 8 年前
        1
  •  0
  •   Nick McCurdy    8 年前

    当您使用导入/导出时,全局变量不会在模块之间共享。这是一件好事,但您可以从模块中导出多个变量。例如,您可以 export locationDataArray;

    当子组件依赖于来自父组件部分数据的数据时,通常应通过道具传递来自父组件的数据子集。添加 location 道具到 MapHolder 与给定的 id 身份证件 它本身然后在

    <MapHolder 
      location={locationDataArray.locations.find(location => location.slug === ID)}
      />
    
        2
  •  -1
  •   Community Mohan Dere    5 年前

    React's Context 特色它的级别相当低,是一个不稳定的API,随时可能发生更改。含义:小心使用。

    在某些情况下,您希望通过组件树传递数据,而不必在每个级别手动传递道具。您可以直接使用强大的“上下文”API进行响应。

    首先,声明您将使子对象可以访问的上下文对象的形状,并实现 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的未来版本中崩溃。

    使用状态管理库(例如)可能会获得更好的结果 redux mobx 管理应该可以从任意组件访问的状态。