I am trying to decide the best route to go for distributing a component that others can theme. They may need to change the html structure as well as the css/bootstrap styling. (I am using react-bootstrap with the component.
The only way I can see to do this is to make a component folder with all of the subcomponents in src/themes/default, src/themes/awesome, etc and then import them into the main component which people can then call by doing something like this...
This is just a concept, it probably isn't completely valid
import default from './themes/default/index.js`
import awesome from './themes/awesome/index.js`
const themes = {
default,
aweosme,
}
const MyComponent = ({ theme, otherprop }) => {
return (
<themes.default otherprop={otherprop} />
)
}
then if someone wanted to contribute a theme, they would have to write a whole component complete with html structure in the jsx and inline styles to go along with it. It would require them to be familiar with react, but I cannot see another way to do it unless I have missed something...
What do you think?
Related
I am fairly new to React and still wrapping my head around custom-hooks. I cam across a code where a custom hook was created to handle the component imports.
useComponentPalette.js
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
const defaultComponents = {
TodoEditor,
TodoItem,
TodoList,
CheckBox
}
export function useComponentPalette(){
return defaultComponents
}
And then in order to use the hook,
const {TodoItem, TodoList, Checkbox } = useComponentPalette()
My Question :- Does this approach provides any advantage over the regular imports in the component ? or this is an anti-pattern ?
How I usually import the components is as follows
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
function App(){
return(
<>
<TodoList/>
</>
)
}
It's not a good idea to use react hooks like this you can get the same result without react hook
// first file name.js
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
export default {
TodoEditor,
TodoItem,
TodoList,
CheckBox
}
//component file
import * as Component form 'first file name';
//<Component.TodoEditor/>
//or
import {TodoEditor} form 'first file name';
The way that I use react-hooks is for making my code more dry and increase it's readability, so react-hooks is not good fit for this kind of usage.
Hi #Sachin,
In my option, React JS use hook to manage reuse stateful logic between components. In other word, Hooks do well to encapsulating state and share logic. If you want to do some stateful logic or condition base logic with these components, then it's fine with that. But if you are using just without condition in the given components. Then, This Is useless for making the custom hook. You can do that without a custom hook in a simpler way.
Here is a simple way to do that:-
In components folder. I create index file, this is the entry point of all my exporting components
In that file. I export all my components, as you can see.
I use that components like this. It much better way. In my option.
import { Header, Footer, Sider } from "./components"
before using react custom hooks, we should be aware of the rationale behind it.
Customs hooks functionality was provided to reuse stateful logic. If logic doesn't require any state, we will use simple functions and if it is about components only there there are different patterns for making code general and scaleable.
So, there is no usage of custom hook in above case at all. For me, I would go with the following code for above scenario:
// components/index.tsx
import {Todo} from './todo'
import {CheckBox} from './components/CheckBox'
export {
Todo,
CheckBox
}
// componentns/todo/index.tsx
import {Editor} from './Editor'
import {Item} from './Item'
import {List} from './List'
const Todo = {
Editor,
Item,
List
}
export default Todo;
and usage will be like
import { Checkbox, Todo } from "components"
...
<Checkbox ... />
<Todo.List ...>
<Todo.Item ... >
</Todo.Editor ... />
</Todo.Item ... >
</Todo.List>
...
P.S Usage can be different based upon the logic of components, just giving an hint how we can patterns to serve our purpose.
Hope it helps.
I am talking about a big web app that has jquery and bootstrap stuff init.
Part of rewriting this giant app using react and material UI, we are writing component by component. Things work fine in general as we make progress toward making this a react app soon.
Our problem:
When a new react component is loaded into the page, the existing (already loaded) react components will lose some or all styles.
We checked the new component load new style (classes) which are matching the names of existing classes for other already loaded components.
Ex:
As you can see, jss1, jss2, ... MuiCardHeader, MuiGrid, ... were also the names for the previously loaded components and now they are overwritten for the newly loaded component.
Packages.json:
webpack config:
Some component code: we are using make style and in some cases withstyle
Tried too much stuff. But nothing seems to work. On initial load, the map has all the correct material-ui stuff but as soon as I click on a marker and the popup component loads in. Now the map is messed up as some styles are overwritten.
How can we make it so that each component styles are named unique and never conflicts with other stuff?
I checked MUI docs and GitHub issues about kinda similar issue but nothing is working for us.
Any thoughts?
If I add:
import { StylesProvider, createGenerateClassName } from '#material-ui/core/styles';
const generateClassName1 = createGenerateClassName({
seed: 'App2',
});
my custom classes ( like root, mydivstyle) will have the prefix like app2-jss1-root, app2-jss2-mydivstyle, ...
but muiCard, MuiCardHeader, ... still being overwritten.
So after a few trial and error. I was able to solve this.
Basically we don't have a component tree path where you can could add a single class generator because of our app structure at this stage. We will soon have one.
The solution was to wrap every component like.
import { StylesProvider, createGenerateClassName } from '#material-ui/core/styles';
const generateClassName = createGenerateClassName({
seed: 'anyprefix',
});
class ActivityContainer extends Component {
render() {
return (
<StylesProvider generateClassName={generateClassName}>
<componenet/>
</StylesProvider>
);
};
}
I had to do this on the container level, this way any component loaded in that container will inherit this prefix.
No more conflicting class names between components and can load them dynamically.
Not a great way but no other option at least in our case. It will leave more classes on the DOM.
Hello i m using storybook/react library to create stories of my components.
So far so good, I followed the tutorial on https://www.learnstorybook.com/react/en/get-started and i have add stories on the left side of the screen with the add command, like so:
add('archived', () => <Task task={{ ...task, state: 'TASK_ARCHIVED' }} {...actions} /> );
The Task component is a functional component.
I 'm also using the storybook-addon-react-live-edit storybook addon, from https://github.com/vertexbz/storybook-addon-react-live-edit for having live edit on the stories, like so:
The code for the above example is this:
``
stories.addDecorator(withLiveEditScope({ React, Test }));
stories.add('simple JSX', withLiveEdit(return <div>hello there!!</div>, {color: 'red'}))`
This code is simple because i just show jsx code.
Problem
I want to live edit a functional or class component, from another file but the functions withLiveEdit(source[, scope]) and addLiveSource(name, source[, scope]), accept only string as the source.
So if i add the story like so: stories.addLiveSource('demo', return ${Test});
Test is a separate Test.js file:
const Test = class Welcome extends React.Component {
render() {
return <h1>Hello, world!!</h1>;
}
}
export default Test;
Results is, it shows the code on 'live tab', but its not actually rendered on the top window.
So my question is, how can i import class or functional components on addLiveSource()/withLiveEdit()
Thanks.
I hit the same issue, you can do this:
storiesOf(group, module)
.addDecorator(withLiveEditScope({ React, SomeFunctionComponent, StyledHeader }))
.addLiveSource("title", `<SomeFunctionComponent><StyledHeader>hello</StyledHeader></SomeFunctionComponent>`);
Basically anything you use inside the template literal in addLiveSource which would need an import you need to add to withLiveEditScope.
The only drawback is you have to write it all inside the template literal (P.S. if you solve that limitation please let me know!)
I am developing a react native app. I am super confused that how to inject javascript code in react native. Though I am struggling somehow to work with react native but the thing is sometimes I need to inject some javascript code in my react native or say the homescreen.js type files, but I somehow end up into a syntax error. For example:
I am trying to implement this in a stylesheet.
const styles = Stylesheet.create({
//some styles
viewStyle:{
Platform.select({
ios:{
marginTop:2,
},
android:{
marginTop:3
}
});
}
//some styles
});
But it just does not work! it doesn't work even when I apply ...Platform instead of Platform.
**Note: I have import {Platform} from 'react-native'
My version is 0.57.something, but what I want to know is what is the syntax to implement javascript in these files. Just like for example in PHP we have the following:
<?php
//your logic
for(something){
?>
<View></View>
<?php
}
?>
Similarly for other languages we have something like the <% %>, {{ }} tags but what should I use in React Native. I always end up with a syntax error.
So my questions are, can anyone help me understand what the restriction is within React Native and where I can use and should not use tags? And if tags are available what are they?
I am super confused and was unable to find a similar question like this anywhere on Stack Overflow. I'd appreciate anyone's inputs, the more answers the more it will be helpful.
So I'm not sure what kind of structure you have set up but I'm going to assume you have a single file (lets call it homescreen.js) and you want to define styles for a component. I'm assuming you have already imported everything that's necessary (StyleSheet, Platform, View and Text from react-native, and the default export React from react).
So first, let's make the stylesheet. You almost have it correct above, you need the following:
const styles = Stylesheet.create({
viewStyle: Platform.select({
ios:{
marginTop:2,
},
android:{
marginTop:3
}
})
})
(You mention above that you're getting a syntax error, this is probably due to the semicolon in your stylesheet object.)
Now we need to create the React class for your HomeScreen component. Again, not sure of the context but you should be able to pull out the bits you need.
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.viewStyle}>
<Text>I should have marginTop 2 on iOS and marginTop 3 on Android.</Text>
</View>
);
}
}
What is alternative way of using package 'react-meteor-data' ? I'm using ES6 for writing react component. What would be best approach for writing meteor subscription in react component so that it will re-render the component if anything change on the server side.
What would be best approach for writing meteor subscription in react
component so that it will re-render the component if anything change
on the server side.
The best approach is using react-meteor-data. What is wrong with this package, that makes you think to not use it?
It even allows you to separate / decouple React Components from Meteor. This is really great because when you reach the point of having written some components that you want to reuse in another non-Meteor project you are free to go without greater hassle.
Of course you could write your own subscription container for react, but with this package you have all important stuff you need plus it is maintained and tested.
If you have trouble setting up a container for subscriptions, you may dig deeper into these tutorials:
https://guide.meteor.com/react.html
https://themeteorchef.com/tutorials/using-create-container
Using react-meteor-data, you first create a HOC container that subscribes to the data and passes it down as props to your component.
Container:
import { createContainer } from 'meteor/react-meteor-data';
export default FooContainer = createContainer(() => {
// Do all your reactive data access in this method.
// Note that this subscription will get cleaned up when your component is unmounted
var handle = Meteor.subscribe("todoList", this.props.id);
return {
currentUser: Meteor.user(),
listLoading: ! handle.ready(),
tasks: Tasks.find({listId: this.props.id}).fetch(),
};
}, Foo);
Component:
import FooContainer from './FooContainer';
class App extends React.Component {
render() {
return (
<div>
{this.props.currentUser.name}
</div>
)
}
}
export default FooContainer(App);
Check out React docs for Higher Order Components to understand how the container works.