LiveBy / react-leaflet-control

Dumb React component for creating Controls
ISC License
88 stars 24 forks source link

Could not find "store" in either the context or props error while rendering a connected component #20

Closed sruthisripathi closed 6 years ago

sruthisripathi commented 6 years ago

DataList - a connected component

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import * as actions from '../actions';

class DataList extends Component {
  componentDidMount() {
    this.props.getData();
  }

  renderList() {
    return this.props.data.map((d) => {
      return (
        <li key={d}>{d}</li>
      );
    });
  }

  render() {
    return (
      <div>
        <ul>
          {this.renderList()}
        </ul>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return { data: state.data };
}

DataList.propTypes = {
  getData: PropTypes.func,
  data: PropTypes.array
}

export default connect(mapStateToProps, actions)(DataList);

MapControl - Map component with control inside whice DataList (the connected component) is rendered

import React, { Component } from 'react'
import {Map, TileLayer} from 'react-leaflet';
import Control from 'react-leaflet-control';
import 'leaflet/dist/leaflet.css';

import DataList from '../components/DataList';

class MapControl extends Component {
  constructor(props) {
    super(props);
    this.state = {
      lat: 17.3850,
      lng: 78.4867,
      zoom: 17,
    };
  }

  render() {
    console.log(this.state); // eslint-disable-line no-console
    const position = [this.state.lat, this.state.lng]
    return (
      <div style={{backgroundColor: '#ffffff', margin:'30px', padding: '50px 30px 50px 30px'}}>
        <Map center={position} zoom={this.state.zoom} style={{height: 500, width: 1165, marginTop: '20px'}}>
          <TileLayer
            attribution="Tiles &copy; Esri &mdash; Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012"
            url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}"
          />;
          <Control position="bottomright">
            <DataList />
          </Control>
        </Map>
      </div>
    )
  }
}

export default MapControl;

Gives me the following error Uncaught Error: Could not find "store" in either the context or props of "Connect(DataList)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(DataList)".

kellyi commented 6 years ago

Hi!

I believe this happens because the way the Control mounts is outside of the Provider's component tree. You can see this using React Dev Tools and inspecting how the virtual DOM looks; here the "Data Card" stuff is the Control:

screen shot 2018-03-18 at 12 28 25 pm

The simplest way to circumvent this would be to connect MapControl to the Redux store, map the store state to props, then pass them as props to the DataList component.

A circuitous alternative I'm not 100% sure would work would be: wrap the DataList in a Provider, using exactly the same store used by the rest of the app.

sruthisripathi commented 6 years ago

@kellyi The first fix you suggested can be used when I just need to get data from redux state. But if I want to dispatch actions from the component rendered inside control, what should I do?

I tried the second fix by Wrapping it in Provider. Still getting the error.

kellyi commented 6 years ago

@sruthisripathi so for dispatching actions, you can pass them in as func props from the parent component too, in a structure like:

<Card handleDispatchAction={arguments => dispatch(actionToDispatch(arguments))}

actionToDispatch can then be called in the control-wrapped component by calling its handleDispatchAction prop.

nishmeht7 commented 6 years ago

@sruthisripathi Add the <Control> wrapper inside the DataList component - that should fix it for you

jgimbel commented 6 years ago

Version 2.0.0 will support this with React's createPortal now.