How to create custom components for Rechart components - recharts

Lets say I am creating a bar chart using Recharts, how would i create a custom component for each of the following Recharts components:
XAxis, YAxis, Tooltip, Legend, CartesianGrid, Cell, and Bar
The reason for this s because i am planning to create a chart with a lot of props and wish to separate all the default props and customization in their own individual component for the list component above.
I have tried just putting the CartesianGrid in a react component and the grid will not show
Any ideas?

It seems that you want to wrap the existing Recharts provided components in a custom component for better organization of your code.
This is currently not supported directly by Recharts, as they check for the type of element that you are rendering and if it does not match one of the allowed types it does not get rendered.
For ex:
<LineChart>
<Line></Line>
</LineChart>
would display a line correctly,
But
function MyLine(props) {
return <Line></Line>
}
<LineChart>
<MyLine />
<LineChart>
would not render the line.
This is because, recharts figures out that the MyLine component is not allowed and hence would not be displayed.
This is a big problem as it does not allow us to reuse or compose components.
But there are some workarounds, one of them being calling your custom component as a function directly:
<LineChart>
{
MyLine({})
}
</LineChart>
It also seems like there are no plans to provide such an api in future. All such issues on their github are already closed, without providing a solution.
https://github.com/recharts/recharts/issues/412
https://github.com/recharts/recharts/issues/41
https://github.com/recharts/recharts/issues/1470

Related

Multiple "<g> attribute transform" errors in kendo UI chart break pdf export

I added kendo chart on a page according to the documentation.
But started to get next error 5 times per each kendo ui chart
Error: <g> attribute transform: Expected number, "matrix(NaN,NaN,NaN,NaN,…".
Charts are drawn but those errors break pdf export. When I use same datasource as in my app on kendo ui dojo.telerik editor there is no error.
I know there might be dozens of possible reasons but I'm a bit locked with that for next few days. So I decided to try luck on stackoverflow in case anyone had anything similar.
Any ideas?
I had the same error, and for me it was related to the <kendo-chart-series-item-labels> component.
I had as property rotation="auto" but the rotation property should be only a number. Removing the property solved it.
<kendo-chart [chartArea]="{ height: 300 }">
<kendo-chart-series>
<kendo-chart-series-item
type="column"
colorField="color"
[gap]="1"
[spacing]="0.25"
[color]="barColor"
[data]="chartData"
[stack]="true"
field="TotalSum"
categoryField="TransactionType"
[tooltip]="{ visible: false }"
>
<kendo-chart-series-item-labels
font="bold 16px unity-medi"
color="#3c3c3c"
rotation="auto"
[margin]="30"
></kendo-chart-series-item-labels>
</kendo-chart-series-item>
</kendo-chart-series>
</kendo-chart>
solution: remove rotation property inside the kendo-chart-series-itme-labels component
Kendo API documentation for this component here: https://www.telerik.com/kendo-angular-ui/components/charts/api/SeriesLabelsComponent/
Of course, in your case, it may come from a different component.
Maybe double check if you have a property inside a kendo-chart or one of its child component that requires only numbers while you may be passing a string or something else to it?

How to get KendoUI Grid to work with custom cell renderer and selection

It seems that the selection events are not being passed through custom cell renderers. My goal is I want to change the background color of every cell in my grid (based on the values), and also be able to handle selection events. I've modified the example in the docs here:
https://www.telerik.com/kendo-react-ui/components/grid/selection/
To include a background color on the Units on Order column. You'll notice that that column does not participate in selections. I created a stackblitz example here:
https://stackblitz.com/edit/react-o4ycqi?file=app/main.jsx
All I changed was I added a cellWithBackground function and assigned it to the column UnitsInStock. Here is that function
const cellWithBackGround = props => {
const examplePrice = true;
const style = {
backgroundColor: "rgb(243, 23, 0, 0.32)"
};
const field = props.field || '';
return <td style={style}>
{props.dataItem[field]}
</td>;
};
I did find an example that was close but it I couldn't get it to work with functional components. It just worked with classes which I don't use. So, please provide examples or references on that support Functional Components.
H Peter,
Thank you for sharing the code. By completely replacing the entire cell's infrastructure, it will no longer respond to anything from the Grid.
Specifically, I'm referring to this line in the function. It only returns a <td> with the field's name, it abandons the rest of the properties of the element.
//cell returned form the function
return <td style={style}>
{props.dataItem[field]}
</td>;
At that point, it's basically a dead cell. It will not respond to events, data actions, etc because it is missing all the parts that the Grid requires to interact with it.
Further Guidance
As I mentioned in my Twitter reply, you can get guidance for the Kendo Engineers to help you from here.
I think there's a better way to handle this by using styling instead of manually handling the DOM elements directly. At the very least, you need to return the complete infrastructure of the cell and they can assist with that.

How can I configure create-react-app to export CSS into two different files

I'm working a project that will dynamically allow the user to change themes, and uses reactstrap and styled-components under the hood. We want to configure all of the variables via SASS, which is working fine. In order to make those variables available to styled-components, we have been using sass-extract-loader to create theme objects.
This all works great when we statically choose one of the themes, but I haven't been able to get it working dynamically reliably. I have two issues:
1) In development, it works fine to switch the theme once. If I change it again, my non-styled-components (i.e., raw reactstrap components) are styled with the second theme. I believe this is because the second theme is loading and overriding the original CSS.
2) In production, I get the same mix as #1 by default (i.e., because all of the CSS files are being put together into a single bundle, reactstrap components are styled one way, while styled-components "honors" the theme).
I believe the best option for us is to have the themes in two separate CSS files, and to toggle "alternate" rels on them. I just don't know how to configure CRA not to put all of the CSS into a single main bundle, and let me manually add links to alternate stylesheets. If I can split them out into separate files, I believe I can just add tags and dynamically swap the rel="alternate" property.
There may well be better ways to accomplish this. My understanding is that the easiest way to control the Bootstrap themes is via SASS variables, and I'd like to make sure those variables don't have to be re-defined when using them in styled-components.
If you want to apply styles conditionally, you can import your stylesheets in your index.js file and make it available to all your components through the context API. First of all we import the CSS files into index.js.
import themeA from './css/themeA.css';
import themeB from './css/themeB.css';
However, by using it this way, you cannot have element selectors in both CSS files, because they would be globally applied from both files. However, you could import an extra stylesheet that complements the selected theme, in which you define the element selectors.
By using CSS modules, you avoid the need for element selectors. You may want to read this article if you are unfamiliar with CSS modules: https://javascriptplayground.com/css-modules-webpack-react/
If you still need to apply element selectors in one theme, you can do so, but they will also get applied in your other theme this way.
import './css/default.css';
This example below is a modified version from the React documentation: https://reactjs.org/docs/context.html
In this example, we draw a button that changes the global theme when
it its clicked. There are three parts in this example that are crucial
to understand if you want to use React its context API.
1. Creating a Context.
Creating a Context is being done by assigning the return value of React.createContext(yourValue) to a variable. This variable can then be used to use the Provider or Consumer component inside your React components.
const ThemeContext = React.createContext();
2. Providing a value by passing it to your Provider component as prop. Now your value is accessible to all your components.
class App extends React.Component {
swapTheme() {
this.setState({ withThemeA: !this.state.withThemeA });
}
render() {
const theme = this.state.withThemeA ? themeA : themeB;
return (
<ThemeContext.Provider value={theme}>
<ThemedButton onClick={this.swapTheme} />
</ThemeContext.Provider>
);
}
}
3. Listening to updates with the Consumer component.
To listen for changes, you need to use the Consumer component. The passed function receives the theme as an argument so it can be assigned to the className prop of the button element.
class ThemedButton extends React.Component {
render() {
return <ThemeContext.Consumer>
{theme => <button className={theme.Button}}>click me</button>}
</ThemeContext.Consumer>;
}
}

ReactJS, React-Router Getting previous path

I am trying to make a single page application in which I have 3 components : Index, BluePage and GreenPage
I'm trying to use React and React router to switch through them. The layout is as follows:
This view is supposed to be like a sliding page and can be better visualized like this following diagram:
In order to do these transitions, I am currently using ReactCSSTransitionGroup and CSS classes, however it is becoming difficult as the direction the page must animate depends on the page that was being viewed before.
For example, if the BluePage was in view, and the user pressed the "back", button, the Index should move into view from the right.
On the other hand, if GreenPage was originally in view, the Index should move into view from the left.
The Question
How can I use React Router to send the existing path to the next component, so I can animate the components properly?
Should I continue to use ReactCSSTransitionGroup or should I handle animations in the componentWillMount and componentWillUnmount callbacks?
If so, how does adding CSS classes to objects after initial rendering work?
I apologize if these questions seem somewhat novice - I am still a beginner to ReactJS. Thanks for all the help!
If any clarification is necessary, let me know.
I would recommend you to check react-swipeable-views.
In this component, you just need to add all of your views (components) as children of the SwipeableView component. The currently active view is defined by index prop of the SwipeableView. You switch the view with buttons, you simply need to create a state in the main component (App, for example) and update this state in onClick handler. It would look like this:
class MainComponent extends Component {
state = {
index: 0,
}
onBlueButtonClick() {
this.setState({ index: 1 });
}
render() {
return (
<div>
<div onClick={() => this.onBlueButtonClick()}>Click me!<div />
<SwipeableView index={this.state.index}>
<BlueView />
<GreenView />
<RedView />
<SwipeableView />
</div>
);
}
}
Hope it helps! ;)
EDIT: I have added a button in the example to explain how to use this component when there is no swipe effect. This is a React component and not a React Native, so it was made to work on a website, therefore without a swipe. I use it in one of my projects. Here's a GIF of it.
What I would suggest you is tu use swiper.js. Why?
performant (desktop, mobile)
no jquery needed
huge api, with very usefull features for your use case
change slide programmatically: swiper.slideTo(2) or swiper.nextSlide())
Hash/History Navigation: sync between hash and slides
you can disable touch gestures
etc..
Setup
npm install swiper --save
Import
const Swiper = require('swiper');
or
import Swiper from 'swiper';
Usage
see demos with example

EmberJS: programmatically adding a child view to a collection view without changing underlying content

My EmberJS app is confusing me a lot at the moment. I have a collection view, that in turn defines an itemViewClass of a custom view I have defined in my code. Something like:
App.CarouselView = Ember.CollectionView.extend({
itemViewClass: App.SlideView.extend(),
});
And this CarouselView is rendered inside a template that has a dynamic segment backing it (I hope this makes sense?) . The controller for these dynamic segment is an array controller because the model for these dynamic segments is a collection :) (more confusion, please let me know)
App.SlidesController = Ember.ArrayController.extend();
By now all of you have figured that I am basically rendering a bunch of slides inside of a carousel. And these are dynamically backed in the collectionView by setting the property
contentBinding:'controller' // property set in CarouselView, controller corresponds to SlidesController
The confusion begins now. I want to add a slide to the existing set of slides. So I provide a button with an action : 'add' target='view'
In the SlidesView,
actions:{
add: function(){
var carouselView = this.get('childViews')[0];
// SlidesView has carouselView and another view as it's child, hence this.get('childViews')[0] is carouselView
var newCard = carouselView.createChildView(App.SlideView.extend());
carouselView.get('childViews').pushObject(newCard);
}
}
The above piece of code sucks and hurts me bad. I want to basically add a new SlideView to my CarouselView collection programmatically upon a button trigger. But apparently Ember recommends that childViews should not be manipulated directly and I ought to instead change the underlying content.
It states in my console.log that manipulating childViews is deprecated etc.
So essentially I need to add something to my content to my SlidesController content ? However, I don't want to add something to the content, this is just a soft add, that is providing the user with a slide so that he may choose to edit or add something if he wants to. He can always discard it. A hard add that will require me to persist the new slide to the DB will come once the user decides to save this information.

Resources