Are there any working react examples of kepler.gl? - javascript

Right now there is an open, breaking bug in the provided kepler.gl React examples.
The open issue:
https://github.com/keplergl/kepler.gl/issues/983
The React examples that currently don't seem to work:
https://github.com/keplergl/kepler.gl/tree/master/examples
I'm trying to get a kepler.gl map working in my React app. I can see the sidebar and other extraneous things show up but the actual map itself does not. If anybody has any working examples of integrating a kepler map into a React app I would love to see it but also if anybody knows why my current integration is broken that would also be of great help.
In my index.js file I have:
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, combineReducers, compose} from 'redux';
import { Provider } from 'react-redux'
import ReduxThunk from 'redux-thunk'
import * as serviceWorker from './serviceWorker';
import axios from 'axios';
import App from './components/App';
import config from './config';
// reducers
import auth from './reducers/auth';
import runtime from './reducers/runtime';
import navigation from './reducers/navigation';
import posts from './reducers/posts';
// import reducers from './reducers';
import keplerGlReducer from 'kepler.gl/reducers';
import {enhanceReduxMiddleware} from 'kepler.gl/middleware';
axios.defaults.baseURL = config.baseURLApi;
axios.defaults.headers.common['Content-Type'] = "application/json";
const token = localStorage.getItem('token');
if (token) {
axios.defaults.headers.common['Authorization'] = "Bearer " + token;
}
const reducers = combineReducers({
auth,
runtime,
navigation,
posts,
// <-- mount kepler.gl reducer in your app
keplerGl: keplerGlReducer,
});
const store = createStore(
reducers,
applyMiddleware(
ReduxThunk
)
);
ReactDOM.render(
<Provider store={store}>
<link rel="stylesheet" href="https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/uber-fonts/4.0.0/superfine.css"></link>
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css" rel="stylesheet"></link>
<script src="https://unpkg.com/kepler.gl/umd/keplergl.min.js"></script>
<App />
</Provider>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
And in my map component I have:
import React from 'react';
import {connect} from 'react-redux';
import KeplerGl from 'kepler.gl';
import {addDataToMap} from 'kepler.gl/actions';
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
const sampleTripData = {
fields: [
{name: 'tpep_pickup_datetime', format: 'YYYY-M-D H:m:s', type: 'timestamp'},
{name: 'pickup_longitude', format: '', type: 'real'},
{name: 'pickup_latitude', format: '', type: 'real'}
],
rows: [
['2015-01-15 19:05:39 +00:00', -73.99389648, 40.75011063],
['2015-01-15 19:05:39 +00:00', -73.97642517, 40.73981094],
['2015-01-15 19:05:40 +00:00', -73.96870422, 40.75424576]
]
};
const sampleConfig = {
visState: {
filters: [
{
id: 'me',
dataId: 'test_trip_data',
name: 'tpep_pickup_datetime',
type: 'timeRange',
enlarged: true
}
]
}
};
class Maps extends React.Component {
componentDidMount() {
this.props.dispatch(
addDataToMap({
datasets: {
info: {
label: 'Sample Taxi Trips in New York City',
id: 'test_trip_data'
},
data: sampleTripData
},
option: {
centerMap: true,
readOnly: false
},
config: sampleConfig
})
);
}
render() {
return (
<div style={{position: 'absolute', left: 0, width: '100vw', height: '100vh'}}>
soimething
<AutoSizer>
{({height, width}) => (
<KeplerGl
id="map"
width={width}
mapboxApiAccessToken={"my mapbox token"}
height={height}
/>
)}
</AutoSizer>
</div>
);
}
}
const mapStateToProps = state => state;
const dispatchToProps = dispatch => ({dispatch});
export default connect(mapStateToProps, dispatchToProps)(Maps);

I don't see anything glaringly out of order in your example but if the UI is showing up and the map is not, it could be the Mapbpox-related imports and tokens etc. Would be good to inspect your console for errors or warnings and also check the network tab.
I imported a working example I have with Create React App plus Typescript and KeplerGL into Codesandbox for your reference if you still need it: https://codesandbox.io/s/create-react-app-typescript-keplergl-bv0vb

Save a .env file in root and give ur React_API=
it will work

Related

Refactoring thunk slices to RTK-Query causing top-level API calls invalid

I'm working on an app using react / redux / redux-toolkit.
Until now, I was using createAsyncThunk to wrap API calls, but for more convenience I decided to use RTK-Query.
It works fine in most cases. However, there's a situation in which I'm unable to make it work. This is when I want the API call to be done directly at the app startup, in the index.js file, as follows :
Working version :
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from "react-redux";
import App from './App';
import store from './store';
import {fetchUserInfo} from "./features/user";
store.dispatch(fetchUserInfo());
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('root')
);
Here, the store.dispatch(fetchUserInfo()); is placed here so that store.user.info will be available in any subsequent component.
The definition of the fetchUserInfo() is made here :
features/user.js
import { createSlice, createAsyncThunk } from '#reduxjs/toolkit'
import {apiCall} from "./utils";
export const fetchUserInfo = createAsyncThunk(
'user/info',
async (thunkAPI) => {
const res = await apiCall('https://my.api/userinfo').json();
return res;
});
export const userSlice = createSlice({
name: 'user',
initialState: { info: '' },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUserInfo.fulfilled, (state, action) => {
state.info = action.payload;
})
},
});
export default userSlice.reducer;
What I would like to do is replace this slice by something like that :
Errored Version :
api/user.js
import { createApi, fetchBaseQuery } from '#reduxjs/toolkit/query/react'
const rawBaseQuery = (baseUrl) => fetchBaseQuery({
baseUrl,
prepareHeaders: (headers, {getState}) => {
headers.set('Authorization', '*******');
return headers
}
});
export const baseQuery = async (args, api, extraOptions) => {
const baseUrl = api.getState().api.root; // 'https://my.api'
return rawBaseQuery(baseUrl)(args, api, extraOptions);
};
export const userApi = createApi({
reducerPath: 'user',
baseQuery: baseQuery,
endpoints: (builder) => ({
getUserInfo: builder.query({
query: () => `/userinfo`
}),
}),
});
export const {
useGetUserInfoQuery
} = userApi;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from "react-redux";
import App from './App';
import store from './store';
import {useGetUserInfoQuery} from "./api/user";
store.dispatch(useGetUserInfoQuery());
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('root')
);
But, I can not call useGetUserInfoQuery() in ìndex.js. The following error occurs :
React Hook use query cannot be called at the top level.
I also tried to call useGetUserInfoQuery() without dispatch but the same error occurs.
How should I proceed? Thanks!

How to access react-redux store outside react component in redux-toolkit?

I am trying to access redux-store in my helper function.
My store looks like code below:
import { combineReducers, configureStore } from '#reduxjs/toolkit';
import createSagaMiddleware from 'redux-saga';
import counterReducer from 'app/Components/Counter/counterSlice';
import languageReducer from 'redux/features/app_language/language.slice';
import loginReducer, {
currentUserReducer,
currentUserIdReducer,
} from 'redux/features/app_login/loginSlice';
import rootSaga from 'redux/sagas';
import emailEditorReducer from 'redux/features/email_editor';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const configureCustomStore = () => {
const sagaMiddleware = createSagaMiddleware();
const persistConfig = {
key: 'root',
storage,
};
const rootReducer = combineReducers({
counter: counterReducer,
app_language: languageReducer,
isAuthenticated: loginReducer,
currentUser: currentUserReducer,
currentUserId: currentUserIdReducer,
emailEditor: emailEditorReducer,
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}).concat(sagaMiddleware),
});
const persistor = persistStore(store);
sagaMiddleware.run(rootSaga);
return { store, persistor };
};
export default configureCustomStore();
export const { store, persistor } = configureCustomStore();
console.log(store.getState(), 'State');
As you can see in the last two lines of code i am trying to console.log the state and i am getting the state as expected. But when i am importing the store in my helper function i am getting undefined. Here is how i am doing it
import storeSaga from 'redux/store/store';
const { store } = storeSaga;
Error i am getting is:
TypeError: Cannot destructure property 'store' of 'redux_store_store__WEBPACK_IMPORTED_MODULE_1__.default' as it is undefined.
I was searching for the solution i end up to this who got almost same issue, the answer is also mentioned in the next comment but honestly i didn't understand it.
I may have done something wrong in order of imports i tried all the ways i could.
For the reference you can have a look on my index.js file below:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { Provider } from 'react-redux';
import { I18nextProvider } from 'react-i18next';
import * as serviceWorker from './serviceWorker';
import i18n from './_helpers/utils/i18n';
import storeSaga from 'redux/store/store';
const { store, persistor } = storeSaga;
import App from './app/Pages/App/App';
import { PersistGate } from 'redux-persist/integration/react';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate persistor={persistor}>
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById('root'),
);
serviceWorker.unregister();
I appreciate your help so much. Thanks in advance.
In
export default configureCustomStore();
export const { store, persistor } = configureCustomStore();
you are creating two independent stores.
Also, when importing you import the first of them and call it storeSaga even though this has nothing to do with a saga at all.
Kick the default export out and do import { store } from 'redux/store/store'; everywhere.
That makes it much clearer what you are doing.
If you still have errors after that, you have a circular import somewhere that you need to resolve, meaning that this file imports from a file that also imports this file (maybe with a third file in-between), forming a circle. JavaScript cannot work with that.
You can Inject Store to any file outside react component like this example:
File axios:
let store
export const injectStore = _store => {
store = _store
}
axiosInstance.interceptors.request.use(config => {
config.headers.authorization = store.getState().auth.token
return config
})
File index (root of your project)
import store from './app/store'
import {injectStore} from './common/axios'
injectStore(store)
You can also read about this here:
https://redux.js.org/faq/code-structure#how-can-i-use-the-redux-store-in-non-component-files

Reducers are gone after attempting to implement redux-persist

I am attempting to implement redux-persist to persist a specific reducer only, invoices, version, but in my case, my reducers are all gone.
This is the entry point:
import React, { Component } from "react";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import { persistStore, persistCombineReducers } from "redux-persist";
import { createWhitelistFilter } from "redux-persist-transform-filter";
import { PersistGate } from 'redux-persist/es/integration/react';
import storage from "redux-persist/lib/storage";
import thunkMiddleware from "redux-thunk";
import { apiMiddleware } from "redux-api-middleware";
import reducers from "./actions/reducers";
import AppContainer from "./containers/App";
import FlashMessage from "./containers/common/FlashMessage";
import "./App.css"
const middleware = [thunkMiddleware, apiMiddleware];
const persistConfig = {
storage,
key: 'root',
transforms: [
createWhitelistFilter('invoices')
]
};
const store = createStore(
persistCombineReducers(persistConfig, reducers),
compose(
applyMiddleware(...middleware),
)
);
const persistor = persistStore(store);
export default class App extends Component {
render () {
return (
<Provider store={store}>
<PersistGate persistor={persistor}>
{/*<FlashMessage/>*/} // Since there is no reducer, this fails
<AppContainer/>
</PersistGate>
</Provider>
)
}
}
And this is the reducers file I have:
import { combineReducers } from "redux";
import { routerReducer as router } from "react-router-redux";
import app from "./app";
import invoices from "./invoices/invoices";
import recipients from "./recipients/recipients";
export const makeRootReducer = (asyncReducers) => {
return combineReducers({
router,
app,
invoices,
recipients,
...asyncReducers
})
};
export const injectReducer = (store, { key, reducer }) => {
store.asyncReducers[key] = reducer;
store.replaceReducer(makeRootReducer(store.asyncReducers))
};
export default makeRootReducer;
I have followed many suggestions but I must be missing something.
I found out why. After checking the source code, I saw the following documentation block of persistCombineReducers:
/**
* It provides a way of combining the reducers, replacing redux's #see combineReducers
* #param config persistence configuration
* #param reducers set of keyed functions mapping to the application state
* #returns reducer
*/
export function persistCombineReducers<S>(config: PersistConfig, reducers: ReducersMapObject): Reducer<S & PersistedState>;
The key words were "replacing redux's #see combineReducers".
Removing combineReducers from my reducers file to the following solved the issue:
import { routerReducer as router } from "react-router-redux";
import app from "./app";
import invoices from "./invoices/invoices";
import recipients from "./recipients/recipients";
const reducers = {
router,
app,
invoices,
recipients,
};
export default reducers;

Redux : Cannot read property 'dispatch' of undefined

I'm so confused on why this is undefined. I set up store, and can even view it through Chrome's Redux Tools and it show correctly, however when I try and dispatch to the Store, I always get a Cannot read property 'dispatch' of undefined error. It's really bugging me because I have no idea what is going on. I have followed numerous tutorials letter for letter, and am still stuck with the same error message.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import manageEmails from './reducers/manageEmails';
import App from './App';
import './index.css';
export function configureStore(){
return createStore(
manageEmails,
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
);
};
ReactDOM.render(
<App store={configureStore()} />,
document.getElementById('root')
);
manageEmails.js
export default function manageEmails(state = {
numberOfEmails: 0,
emails: [],
}, action) {
switch(action.type) {
case "ADD_USER":
return Object.assign({}, state, {
emails:state.emails.concat(action.email)
});
default:
return state;
}
}
App.js
import React, { Component } from 'react';
import './App.css';
import $ from 'jquery';
import Typed from 'typed.js';
import AboutDiv from '../src/components/AboutDiv.js'
import ContactDiv from '../src/components/ContactDiv.js'
import Navigation from '../src/components/Navigation.js'
import Background from '../src/components/Background.js'
import Overlay from '../src/components/Overlay.js'
import Emails from '../src/components/Emails.js'
import { BrowserRouter as Router, Route } from "react-router-dom"
$(document).ready(function() {
var options = {
strings: ["dj#khaled.com", "post#malone.com",
"drizzy#drake.com"],
typeSpeed: 175,
backSpeed: 20,
fadeOut: true,
loop: true,
attr: 'placeholder'
}
var typed = new Typed( (".typed"), options);
});
export class App extends Component {
render() {
return (
<Router>
<div className="App">
<Navigation />
<Background />
<Overlay />
<Emails store={this.props.store}/>
</div>
</Router>
);
}
}
export default App;
Emails.js
import React, { Component } from 'react';
export default class Emails extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
};
}
handleOnSubmit(event) {
debugger
event.preventDefault();
this.props.store.dispatch({
type: "ADD_EMAIL",
email: this.state.email,
})
}
render() {
return(
<button onClick={this.handleOnSubmit.bind(this)}>
Click Me
</button>
)
}
};
Check the minimal example I created out of your code and it seems to work as intended. Code can be found at codesandbox
Also, you have a typo there. In the reducer you are checking for a different action then the one being dispatched in the Email component

How to access redux variables and functions from deep components

I'm a bit confused about redux implementation.
Let's say my app has this component structure:
-App
--ProfilationStep
---ProfilationStep1
----React-Select (http://jedwatson.github.io/react-select/)
I need to use redux because the app is going to grow bigger and deeper, so I started by setting up Actions, Reducers and Action types for the React-Select component. I also set the mapStateToProps in the App.js file.
Now I need to know how to pass/access the data stored in redux to other components (React-Select for example) and how to edit it with the actions I declared.
This is my index.js file
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import ProfilationSelectReducer from './components/reducers/profilationSelect';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
const store = createStore(
ProfilationSelectReducer
);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
registerServiceWorker();
This is my App.js
import React, { Component } from 'react';
import PropTypes from 'prop-types'
import { bindActionCreators} from 'redux'
import Profilation from './components/Profilation'
import ProfilationStep from './components/Profilation/ProfilationStep'
import { connect } from 'react-redux';
import * as SelectActionCreators from './components/actions/profilationSelect'
import 'react-select/dist/react-select.css';
class App extends Component {
static propTypes = {
steps: PropTypes.array.isRequired
};
render() {
console.log(this.props)
const { dispatch, steps } = this.props;
const changeValue= bindActionCreators(SelectActionCreators.changeValue, dispatch);
const stepComponents = this.props.steps.map((step, index) => (
<ProfilationStep
key={index}
index={index}
step={step}
/>
));
return (
<div className="repower-app">
{ stepComponents }
</div>
);
}
}
const mapStateToProps = state => ({
steps:state.steps
});
export default connect(mapStateToProps)(App);
This is my ProfilationStep.js file
import React, { Component } from 'react';
import PropTypes from 'prop-types'
import ProfilationStep1 from './ProfilationStep1'
import ProfilationStep2 from './ProfilationStep2'
import ProfilationStep3 from './ProfilationStep3'
import ProfilationStep4 from './ProfilationStep4'
import ProfilationStep5 from './ProfilationStep5'
const ProfilationStep = props =>
<div className='ProfilationStep'>
{props.index===0 &&
<ProfilationStep1
step={props.step}
/>
}
{props.stepIndex===2 &&
<ProfilationStep2
handleSelect={props.handleSelect}
handleInput={props.handleInput}
expend={props.expend}
period={props.period}
light={props.light}
gas={props.gas}
/>
}
{props.stepIndex===3 &&
<ProfilationStep3
handleSelect={props.handleSelect}
environment={props.environment}
/>
}
{props.stepIndex===4 &&
<ProfilationStep4
flexibility={props.flexibility}
handleSelect={props.handleSelect}
/>
}
{props.stepIndex===5 &&
<ProfilationStep5
customize={props.customize}
handleSelect={props.handleSelect}
/>
}
</div>
export default ProfilationStep
This is my ProfilationStep1.js file
import React, { Component } from 'react';
import Select from 'react-select';
import PropTypes from 'prop-types'
var jobOptions = [
{ value: 'edilizia', label: 'Edilizia' },
{ value: 'editoria', label: 'Editoria' },
{ value: 'educazione', label: 'Educazione' }
];
const ProfilationStep1 = props =>
<div className='ProfilationStep'>
La mia attività si occupa di <Select
name="job"
value={props.step.job}
onChange={e => props.changeValue(e.target.value)}
options={jobOptions}
/>
</div>
ProfilationStep1.propTypes = {
//isComplete: PropTypes.bool.isRequired,
//isActive: PropTypes.bool.isRequired
job: PropTypes.string.isRequired,
service: PropTypes.string.isRequired,
handleSelect: PropTypes.func.isRequired
}
export default ProfilationStep1
This is my reducer
import * as ProfilationSelectActionTypes from '../actiontypes/profilationSelect';
const initialState = {
steps: [{
job: "",
service: ""
}],
}
export default function ProfilationSelectReducer (state=initialState, action){
switch(action.type){
case ProfilationSelectActionTypes.CHANGE_VALUE:
return {
...state,
steps:[{
job: action.value
}]
};
default:
return state;
}
}
This is my actiontypes file
export const CHANGE_VALUE ='profilationSelect/CHANGE_VALUE';
and, finally, this is my actions file
import * as ProfilationSelectActionTypes from '../actiontypes/profilationSelect';
export const changeValue = value =>{
return{
type: ProfilationSelectActionTypes.CHANGE_VALUE,
value
}
}
Thank you for any help
You are definitely on the right way.
The solution is simple: You bind your state to the react props. With the props, you can do whatever you like (e.g. pass them to react-select). If you want to modify it, you have to map "mapDispatchToProps", where you map functions, which execute your actions to the props. This works the same as "mapStateTopProps":
End of App.js (import your actions file on top, named "profilationSelectActions" here):
const mapStateToProps = state => ({
steps:state.steps
});
const mapDispatchToProps = dispatch => ({
updateJobValue: (value) => dispatch(profilationSelectActions.changeValue(value))
}
// Also add here mapDispatchToProps
export default connect(mapStateToProps, mapDispatchToProps)(App);
Now the function "updateJobValue" is available in the props of your app.js. You can now easily pass it down to your components and to the onChange event of react-select:
In your ProfilationStep1.js change this line:
onChange={e => props.changeValue(e.target.value)}
To this (after you passed the function updateJobValue down)
onChange{e => props.updateJobType(e.target.value)}
After that, updateJobType should go all the way up to App.js and then dispatch the action. After that, the application will re-render with the new steps.

Categories

Resources