React JS: Reusable and modifiable ui components? - reactjs

I just started working on a project and I decided to use ant design package. I want to create reusable and modifiable components. For instance, I want to create a button component and use it in entire app instead of using antd's button component directly. Therefore, if I decided to change how the button looks I will just change button component I created. So if I decided to use another ui package I just need to change button component or style of it instead of changing it in entire app. I am actually a back-end developer and do not have much knowledge on front-end. I wanna know if my approach is proper or not. I am asking because bellow code does not seem proper to me:
import React from 'react';
import { Button } from 'antd';
function myButton(props) {
return (
<Button {...props}>
{props.children}
</Button>
);
}
export default myButton;
In other files:
import { Button } from './components/button';
Instead of:
import { Button } from 'antd';
Should I use this approach in that way or extend these components without a change (or export them directly from components directory)?

Related

How to share custom-styled Ionic components in bit.dev

Could you please help with the following?
We use Ionic with React in a team having 2 distinct projects.
We need to style these Ionic components a little differently.
I need to share these a-little-differently-styled Ionic components with another team for code re-use.
I would like to showcase these styled Ionic components using Storybook to the UX team and say "this is how a button looks like"
To begin with I just added the styling in a css file and imported that file in the root React page.
But it would be nice to just encapsulate component + styling in a re-usable isolated component that other people can re-use without having to import custom css files.
I am thinking of :
import { IonButton } from "#ionic/react";
import styled from "styled-components";
const StyledIonButton = styled(IonButton)`
// some custom css styling here
`;
const MyIonButton = () => <StyledIonButton {...props} />;
export default MyIonButton;
Now, I can track/export above component using e.g Bit.dev and have the other team consume it via npm-install.
However, I dislike :
a) changing the name from "IonButton" to "MyIonButton"
b) having to wrap each and every Ionic component as shown above
I would like myself and the other team to just use Ionic components in the standard way e.g
import { IonButton } from "#ionic/react";
...
<IonButton>Close</IonButton>
BUT having these base building-blocks/components styled in a certain way.
Could you please describe to me the right approach please? Many thanks for your time

Reusing custom styles in material-ui

New to material-ui here and trying to work out the best way of using the css in js. I can see from the demo code that inserting styles as classes is pretty easy using 'withStyles' but if I do the following I'd need to re-create the 'grow' and 'defaultPadding' styles in every component.
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import Paper from '#material-ui/core/Paper';
function Dashboard(props) {
const { classes } = props;
return (
<Paper className={classes.defaultPadding}>
Hello
</Paper>
);
}
const styles = theme => ({
grow: {
flexGrow: 1
},
defaultPadding: {
padding: theme.spacing.unit * 3 + 'px'
}
});
export default withStyles(styles)(Dashboard);
I could easily create a factory method in an external file that returns a massive object containing all my default styles but I'd need to be able to pass the existing theme to it if I want to use things like 'theme.spacing.unit'.
So, is there a way to create a bunch of re-usable styles of my own, using theme values, then import them into any component?
Bonus question: Is it possible to create nested objects so I can do things like this? ...
className={classes.layout.header}
I think creating an external factory method would work or you could also create a ThemeProvider to pass your theme to every component that needs the same styles.
In the Codesandbox I created two Dashboard components. One with styled-components just to show how a ThemeProvider works and the other component is using withStyles.
For withStyles factory I called it sharedStyles in the demo and with this you can create a new style object inside your components by calling it and spreading it to a new style (just if you need to add more styles).
Nesting inside styles seems not supported. You could create keys like layout.heading or flatten the object before using it (see code in the demo). Both not perfect and I wouldn't use it.
I'm personally prefering styled-components but you don't need to switch to it. You can look at the source code how they implemented it and use it in your code to pass the theme to your component.
The ThemeProvider is using React Context-Api.

Extending an already defined component in react

I've got a component named Button in a react library and would like to extend its capabilities furthermore. The following is the code which I wrote.
import React from 'react';
import { Button } from 'reactstrap';
export class Button extends React.Component {
render () {
return (
<Button color="primary" className="Button">primary</Button>
);
}
}
I would like to use the same name as the already defined component. The problem is, when I run the application, I get an error saying,
Uncaught Error: Module build failed: C:/Users/dimal/Documents/GitHub/theme-wso2/module/components/MaterialButton.js: Duplicate declaration "Button"
How can I import the component I would like to extend in another name? as far as I think, if I rename the component this issue would go away! Am I correct?
You can name your Button from reactstrap to a diff name. To achieve this write something similar to below
import { Button as BootStrapButton } from 'reactstrap';
Now use BootStrapButton in places where you want to use button from reactstrap.

Can we have React 16 Portal functionality React Native?

I'm using React Native which ships with React 16 alpha release which supports portals. While in browser and having access to DOM we can use id or classes to access element from anywhere in component/file hierarchy like this:
const modalRoot = document.getElementById('modal-root');
and pass it to createPortal(child, container) container arg. React docs clearly says than container should be DOM element:
The second argument (container) is a DOM element.
This function is also a method of ReactDOM which doesn't exist in React Native.
Is there a way to achieve the similar functionality in React Native?
Use case:
I want to render an animated overlay in the root of my application but pass the Animated values props to it from a parent deep in the tree hierarchy (can't use Redux actions for such things).
I had similar problem where I wanted to render overlay on top of everything from deeply nested child component. I solved my problem with React Native's Modal
It renders its content on top of everything :) Easy to use and no need for extra dependencies
I don't think react-native provides this functionality in its own API.
But there is a library available which provides the similar functionality. react-gateway
As per the docs of react-gateway,
It also works in universal (isomorphic) React applications without any additional setup and in React Native applications.
React Gateway does not directly depend on react-dom, so it works fine with React Native under one condition:
You must pass React Native component like View or similar to component prop of .
import React from 'react';
import { Text, View } from 'react-native';
import {
Gateway,
GatewayDest,
GatewayProvider
} from 'react-gateway';
export default class Application extends React.Component {
render() {
return (
<GatewayProvider>
<View>
<Text>React Gateway Native Example</Text>
<View>
<Gateway into="one">
<Text>Text rendered elsewhere</Text>
</Gateway>
</View>
<GatewayDest name="one" component={View} />
</View>
</GatewayProvider>
);
}
}
The above example is taken from the repo itself. react native example
One way to render the items above the screen can be done using react-native-paper library.
import * as React from 'react';
import { Text } from 'react-native';
import { Portal } from 'react-native-paper';
const MyComponent = () => (
<Portal.Host>
<Text>Content of the app</Text>
</Portal.Host>
);
export default MyComponent;
Portal host renders all of its children Portal elements. For example, you can wrap a screen in Portal.Host to render items above the screen.
Here is the link which describes its usage:
https://callstack.github.io/react-native-paper/portal-host.html

Combining components to one library

Im currently creating a UI library for my react native project.
The components are separated into its own files like: Button, TextBox, Panel etc etc
So when i want to use them I do:
import Button from '../UI/button';
import TextBox from '../UI/textBox';
But how could I impletement the following call instead? Not needing to do import statetments for each specific component.
import { Button,TextBox, SomeOtherComp } from '../UI/??';
This would save a lot of typing when I want to use multiple components...
Create a file called index.js
The purpose of this file is to simple expose all available components from your library
import Button from './button';
import TextBox from './textBox';
...
module.exports = {
Button,
TextBox,
...
};
In the code that consumes your UI library, you can now import the components like this:
import { Button, TextBox, SomeOtherComp } from '../UI';
When you import a folder name, the packages will look for an index.js file and import that.
It is possible to re-export modules directly without writing duplicate code for importing and exporting:
// UI.js
export { default as Button } from './button';
export { default as TextBox } from './textBox';
Usage:
import { Button, TextBox } from './UI';

Resources