Openlayers ol-ext select multiple features to transform - reactjs

I am using the ol-ext extension for Openlayers, which is awesome.
The piece I am interested in is the Transform interaction, I have it working inside a basic React example here: https://jsfiddle.net/mcneela86/umrz7dd1/
This is the extent of the component so far:
class Select extends React.Component {
static contextTypes = {map: PropTypes.object}
componentDidMount() {
this.select = new ol.interaction.Transform();
this.context.map.addInteraction(this.select);
console.log(this.select);
}
componentWillUnmount () {
this.context.map.removeInteraction(this.select);
}
render() { return null; }
}
My question is, is there a way I can select multiple features at once?

The Transform interaction is assumed to handle only one feature.
More than one could be used but I need use cases to see what's happened (should each feature rotate individualy? around which center? etc.).
You can ask for a enhancement on the github page.

Related

How to use the new #Shopify/app-bridge with #Shopify/polaris-react

Shopify recently released their new #shopify/app-bridge, but it is unclear to me how it should be used alongside #shopify/polaris.
For example, I have tried to make a React component that will use the app-bridge and polaris to display a toast.
import React, { Component } from "react";
import * as PropTypes from "prop-types";
import { Toast } from "#shopify/app-bridge/actions";
import { Page } from "#shopify/polaris";
class Start extends Component {
static contextTypes = {
polaris: PropTypes.object
};
showToast() {
console.log("SHOW TOAST");
console.log(this.context.polaris.appBridge);
const toastNotice = Toast.create(this.context.polaris.appBridge, {
message: "Test Toast",
duration: 5000
});
toastNotice.dispatch(Toast.Action.SHOW);
}
render() {
this.showToast();
return (
<Page title="Do you see toast?">
<p>I do not see toast.</p>
</Page>
);
}
}
export default Start;
But it does not seem to dispatch the action. Any ideas on why not? Note that my app is wrapped in the AppProvider and app-bridge is initialized.
ReactDOM.render(
<AppProvider
apiKey={process.env.REACT_APP_SHOPIFY_API_KEY}
shopOrigin={queryString.parse(window.location.search).shop}
>
<Start />
</AppProvider>,
document.getElementById("root")
);
Any suggestions?
So after a lot of debugging, I found out from Shopify that inside App Bridge, before taking any action, they check that the localOrigin matches the appURL (one that's entered in the partners dashboard). In my case, I have a backend (node.js on heroku used for authentication) and a frontend (react bundle on firebase) my app starts by hitting the backend, and then if authentication checks out, it redirects to the front end. And hence the localOrigin does not match... hmmm, I'm very glad to have figured this out since I lost a lot of sleep over it. Now the question is what to do about it... maybe this is something that could be updated with AppBridge? Or is there a better design I should be considering?
There is now #shopify/app-bridge-react,
https://www.npmjs.com/package/#shopify/app-bridge-react
Shopify supposedly doesn't have docs for it yet though... But, someone can update my answer when they come out with them. :)
NOTE:
Be sure to have, static contextType = Context; to get access to this.context for dispatching actions/etc in your components.
(Hopefully this saves you days of suffering haha I'm not a React developer, so, yeah... this was not marked as "crucial" or anything in the examples).
I also wanted to address #SomethingOn's comment, but I don't have enough reputation to comment...
You actually can debug an iframe. In chrome dev tools, on top where it says "top", you can actually select a frame that you want to debug.
https://stackoverflow.com/a/8581276/10076085
Once you select the Shopify App iframe, type in "window.location" or whatever you want!
Shopify's docs and examples are limited and I'm running into a bunch of issues myself working on a Shopify App, so I just want to spread help as much as possible!

React Firebase Callback

I started learning React using Firebase about one year ago, and it's all going pretty well, I guess. However, ever since I started writing, I really miss mastering the art of callbacks like I did with Swift.
I feel that there's barely any information that's going straight to the point regarding callbacks and Firebase using React. For instance, there has been so many times I want to be able to use callbacks, but have ended up writing numerous extra functions to perform the exact same task. For instance, I want to be able to call a function, and then return a value inside a Snapshot.once. But how?
You see, this is an example of an issue I'm facing at this very moment. I'm currently mapping out a list of users on my website, with the following information: firstname, lastname and companyId. Upon display, I want to be able to verify that the companyId does in fact exist in a separate table called 'Companies' structured like this:
Companies -> uniqueCompanyId -> information
I know that I can't return values in an async function, but this is what I am thinking about:
isCompanyVerified(input){
databaseCompanies.child(input).once('value', (snapshot) => {
if(snapshot.val().isVerified){
return true;
} else {
return false;
}
})
}
<div>
allUsers.map((singleUser) => {
return(
<p>{singleUser.name}</p>
<p>{this.isCompanyVerified(singleUser.companyId)}</p>
)
})
</div>
It would really mean the world to me if someone could explain to me how I would do this the correct way, or at least point me in the right direction. The problem is that I honestly don't know where to seek information.
I'm used to having code structured with having all networking/database functions in one file, like I did in Swift called ex. 'Networking.swift'. And then do function calls that I fetch from the specific file. Using React, I have ended up having all of my code in each Component, resulting in a lot of duplicated code, a lot of extra work and making it all look unstructured.
I'm fairly familiar to the syntax right now, and I do believe I have learned a lot, yet - I feel that I do numerous things the wrong way, and still have a lot to learn. Where would be the best place for me to learn to really master React? Going from intermediate to an 'experienced' (writing and structuring React code like it's supposed to be done).
All help is appreciated. I'm making this post as I really want to put in the effort to learn.
You cannot directly write the dom in react like this. The dom is not being re-rendered in this case. Store the verification data in a state and the dom is being re-rendered as soon as the async data arrived.
SOLUTION 1
This is an implementation of a single UserItem component:
UserItem.js
class UserItem extends React.Component {
state {
isUserVerified: false
}
handleVerified = snapshot => {
this.setState({ isUserVerified: snapshot.val().isVerified })
}
componentDidMount {
const {userId} = this.props;
databaseCompanies.child(userId).once('value', this.handleVerified)
}
render() {
const { isUserVerified } = this.state;
return (
<div>{isUserVerified ? 'verified' : 'not verified'}</div>
)
}
}
UserList.js
...
render(){
allUsers.map(singleUser => <UserItem userId={singleUser.id} />
}
SOLUTION 2
If you'd like to list all the users, get a snapshot from the complete users object
componentDidMount {
databaseCompanies.child('users').once('value', this.handleStoreUsers)
}
This will result something like this in the state:
state = {
users: {
_key1: { id..., verified: true },
_key2: { id..., verified: false }
...
}
}
And map trough them.

How to display progress to user during long running process in React

I am building an app where a user provides a file and some parameters to then perform a long running task. I have all of that working. What is not working is showing the user the current progress of processing. I have a simple CodePen set up to illustrate.
In the Pen, I have a button that runs a task in a while loop. If I am looking at the console, I can see the progress printing out as we step through the loop. However, the state isn't updating until the loop is done, so in the UI the progress jumps from 0 to 5 without displaying the intermediate values. Here I am simulating the task with the sleep function, I do not actually use the sleep function in my app.
I've done some research and I know this has to do with setState being asynchronous and with React batching updates together to be more efficient with rendering the UI.
With that being said, I am wondering what the best way to display progress to the user would be. Using React's state doesn't work, and I've tried directly writing to the DOM but that wasn't working (and it didn't seem like a clean way to do it). Do I need to use some additional library to do this or is there something I am missing? I was considering moving this to a separate process and then communicating the progress back to the app, but wouldn't I run into the same issue of the UI not updating?
Also potentially important, I am using the while loop because I am using a generator, so I know I won't receive too many progress updates because yield runs each percentage point from 0 to 100. It is also easy for me to remove the generator/yield part if that would be better.
My code is in CodePen as well as below:
---HTML---
<div id="app"></app>
---JSX---
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
progress: 0
};
this.doTask = this.doTask.bind(this);
this.sleep = this.sleep.bind(this);
}
sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
doTask() {
let count = 0;
while(count<5) {
count++;
console.log(count);
this.setState({
progress: count
});
this.sleep(500);
}
}
render() {
return <div>
<button onClick={this.doTask}>Do Task</button>
<div>Progress: {this.state.progress}</div>
</div>;
}
}
/*
* Render the above component into the div#app
*/
React.render(<Application />, document.getElementById('app'));
This is a recurring issue in development, so I hope this question and solutions helps you out: Calling setState in a loop only updates state 1 time.
I would also take a look at https://jsbin.com/kiyaco/edit?js,output where an alternate form of this.setState is used. It essentially passed in a function which has access to the current state.
What I ended up doing was creating a background process (aka a hidden window because I'm using electron) that basically acts as a server. The information for my long running process is sent to the background process via a websocket and the progress information is sent back to my main component also via a websocket. Updating the state from a loop seems to me to be more intuitive, but running my code in the background doesn't freeze up the UI and now I get my desired behavior.
I have the same issue and used a workaround. For some reason, when using setTimeout() the page does the setState() processing correctly. It remembered me of runLater in JavaFX.
So this is a workaround I used:
// a wrapper function for setState which uses `Promise` and calls `setTimeout()`
setStatePromise = (state) => new Promise(resolve => {
this.setState(state, () => {
setTimeout(() => resolve(), 1);
});
});
Now you can call this wrapper instead. But you'll need to use async functions:
async doTask() {
let count = 0;
while(count<5) {
count++;
console.log(count);
await this.setStatePromise({
progress: count
});
this.sleep(500);
}
}

How to use React with PowerBI custom visual

I'm trying to progress a Power BI Custom Visual react sample to the stage where it can access the dataViews of the parent visual in the React component.
The sample in question is https://github.com/ignatvilesov/powerbi-visuals-react-sample
Answers to this question may not require expertise in Power BI custom visuals, knowledge of React may be sufficient.
In the Update method of the visual it create the calls ReactDOM.render like this: ReactDOM.render(React.createElement(App), this.element);
This works and creates a component that allows the react component to display elements in the visual.
When I attempt to pass the data options: VisualUpdateOptions like this: ReactDOM.render(React.createElement(App,{options} ), this.element); , I am finding problems.
I don't understand how to get the options object using props, I've tried a variety of things, here is a sample of my attempts at an App.tsx
module powerbi.extensibility.visual {
export class App extends React.Component<any,any> {
constructor(props: VisualUpdateOptions) {
super(props);
}
public render() {
var message = "";
if (this.props == null){
message = "no data"
}
else
{
message = "got data"
}
var message2 = "";
if (this.props.dataViews == null)
{
message2 = "no dataview"
}
else
{
message2 = "got dataview"
}
...
I get data ok, message2 always gives me no dataview.Any advice would be greatly appreciated, I have great ignorance in this area and seek enlightenment :-)
I think you should try to pass the props object to create element inside the visual.ts (where you create an instance of the react app). Something like this:
ReactDOM.render(React.createElement(App, {"yourProp": "props"}), this.element);
Console log the props as you are doing now, you should see them.

How can I persist redux state tree on refresh?

The first principle of Redux documentation is:
The state of your whole application is stored in an object tree within a single store.
And I actually thought that I understand all of the principles well.
But I'm now confused, what does application mean.
If application means just one of little complicated part in a website and works in just one page, I understand. But what if application means the whole website? Should I use LocalStorage or cookie or something for keeping the state tree? But what if the browser doesn't support LocalStorage?
I want to know how developers keep their state tree! :)
If you would like to persist your redux state across a browser refresh, it's best to do this using redux middleware. Check out the redux-persist and redux-storage middleware. They both try to accomplish the same task of storing your redux state so that it may be saved and loaded at will.
--
Edit
It's been some time since I've revisited this question, but seeing that the other (albeit more upvoted answer) encourages rolling your own solution, I figured I'd answer this again.
As of this edit, both libraries have been updated within the last six months. My team has been using redux-persist in production for a few years now and have had no issues.
While it might seem like a simple problem, you'll quickly find that rolling your own solution will not only cause a maintenance burden, but result in bugs and performance issues. The first examples that come to mind are:
JSON.stringify and JSON.parse can not only hurt performance when not needed but throw errors that when unhandled in a critical piece of code like your redux store can crash your application.
(Partially mentioned in the answer below): Figuring out when and how to save and restore your app state is not a simple problem. Do it too often and you'll hurt performance. Not enough, or if the wrong parts of state are persisted, you may find yourself with more bugs. The libraries mentioned above are battle-tested in their approach and provide some pretty fool-proof ways of customizing their behavior.
Part of the beauty of redux (especially in the React ecosystem) is its ability to be placed in multiple environments. As of this edit, redux-persist has 15 different storage implementations, including the awesome localForage library for web, as well as support for React Native, Electron, and Node.
To sum it up, for 3kB minified + gzipped (at the time of this edit) this is not a problem I would ask my team to solve itself.
Edit 25-Aug-2019
As stated in one of the comments. The original redux-storage package has been moved to react-stack. This approach still focuses on implementing your own state management solution.
Original Answer
While the provided answer was valid at some point it is important to notice that the original redux-storage package has been deprecated and it's no longer being maintained...
The original author of the package redux-storage has decided to deprecate the project and no longer maintained.
Now, if you don't want to have dependencies on other packages to avoid problems like these in the future it is very easy to roll your own solution.
All you need to do is:
1- Create a function that returns the state from localStorage and then pass the state to the createStore's redux function in the second parameter in order to hydrate the store
const store = createStore(appReducers, state);
2- Listen for state changes and everytime the state changes, save the state to localStorage
store.subscribe(() => {
//this is just a function that saves state to localStorage
saveState(store.getState());
});
And that's it...I actually use something similar in production, but instead of using functions, I wrote a very simple class as below...
class StateLoader {
loadState() {
try {
let serializedState = localStorage.getItem("http://contoso.com:state");
if (serializedState === null) {
return this.initializeState();
}
return JSON.parse(serializedState);
}
catch (err) {
return this.initializeState();
}
}
saveState(state) {
try {
let serializedState = JSON.stringify(state);
localStorage.setItem("http://contoso.com:state", serializedState);
}
catch (err) {
}
}
initializeState() {
return {
//state object
}
};
}
}
and then when bootstrapping your app...
import StateLoader from "./state.loader"
const stateLoader = new StateLoader();
let store = createStore(appReducers, stateLoader.loadState());
store.subscribe(() => {
stateLoader.saveState(store.getState());
});
Hope it helps somebody
Performance Note
If state changes are very frequent in your application, saving to local storage too often might hurt your application's performance, especially if the state object graph to serialize/deserialize is large. For these cases, you might want to debounce or throttle the function that saves state to localStorage using RxJs, lodash or something similar.
This is based on Leo's answer (which should be the accepted answer since it achieves the question's purpose without using any 3rd party libs).
I've created a Singleton class that creates a Redux Store, persists it using local storage and allows simple access to its store through a getter.
To use it, just put the following Redux-Provider element around your main class:
// ... Your other imports
import PersistedStore from "./PersistedStore";
ReactDOM.render(
<Provider store={PersistedStore.getDefaultStore().store}>
<MainClass />
</Provider>,
document.getElementById('root')
);
and add the following class to your project:
import {
createStore
} from "redux";
import rootReducer from './RootReducer'
const LOCAL_STORAGE_NAME = "localData";
class PersistedStore {
// Singleton property
static DefaultStore = null;
// Accessor to the default instance of this class
static getDefaultStore() {
if (PersistedStore.DefaultStore === null) {
PersistedStore.DefaultStore = new PersistedStore();
}
return PersistedStore.DefaultStore;
}
// Redux store
_store = null;
// When class instance is used, initialize the store
constructor() {
this.initStore()
}
// Initialization of Redux Store
initStore() {
this._store = createStore(rootReducer, PersistedStore.loadState());
this._store.subscribe(() => {
PersistedStore.saveState(this._store.getState());
});
}
// Getter to access the Redux store
get store() {
return this._store;
}
// Loading persisted state from localStorage, no need to access
// this method from the outside
static loadState() {
try {
let serializedState = localStorage.getItem(LOCAL_STORAGE_NAME);
if (serializedState === null) {
return PersistedStore.initialState();
}
return JSON.parse(serializedState);
} catch (err) {
return PersistedStore.initialState();
}
}
// Saving persisted state to localStorage every time something
// changes in the Redux Store (This happens because of the subscribe()
// in the initStore-method). No need to access this method from the outside
static saveState(state) {
try {
let serializedState = JSON.stringify(state);
localStorage.setItem(LOCAL_STORAGE_NAME, serializedState);
} catch (err) {}
}
// Return whatever you want your initial state to be
static initialState() {
return {};
}
}
export default PersistedStore;

Resources