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!)
Related
What I'm trying to achieve is:
Building simple react app - the template is create react app
Copying output file (main.*.js)
Pasting it in another react app
Importing render function to render the first app into the second one
Simple react app code:
interface Props {
greeting: string;
}
export module AppModule {
export const sendGreetings = ({ greeting }: Props) => {
return `Hello ${greeting}`;
};
}
Builder file code:
!function(){"use strict";var n;(n||(n={})).sendGreetings=function(n){var e=n.greeting;return"Hello ".concat(e)}}();
Trying to import this file into another app I get this error:
File 'c:/vscode/test-react-app/test-sc-react/src/main.783e0281.js' is not a module.ts(2306)
Which is obvious. I changed the output file manually to:
export function initApp(){"use strict";var n;(n||(n={})).sendGreetings=function(n){var e=n.greeting;return"Hello ".concat(e)}};
It works but the only function that I'm able to access is initApp but not sendGreetings
I've been struggling with this for a while now and I would really appreciate any helpful suggestions
I used Bit.dev for my components that are used across multiple applications & there is an article regarding your issue
https://blog.bitsrc.io/sharing-react-components-across-multiple-applications-a407b5a15186
I think it would help.
🎯 Solution #1
You can use an iframe to inject your react app:
<iframe src='path-to-your-app.html'/>
🎯 Solution #2
Go with micro-frontend architecture approach. Where a front-end app is decomposed into individual, semi-independent "microapps" working loosely together.
As a starting point, you can try npx create-mf-app instead of the CRA.
You can include your js code directly on run time. You can use window.addEventListener to load js/css incoming from an outside source. You just have to append that js to your document on the load event.
I have created a sample test app as below
import React from 'react';
class App extends React.Component {
render() {
const SampleBtn = (props) => {
console.log('button rendered');
return <button>test</button>;
};
return (
<div className="App">
<SampleBtn />
</div>
);
}
}
export default App;
When I run the above app, console.log('Button rendered') is called twice. I tried to remove <React.StrictMode> also, it is called twice and sometimes it multiplies. How to resolve this and can I know the reason behind this?
I have used HTML button and create a stackblitz code as below, even then I am seeing the logging twice. Please see the url below
https://react-xd9pzh.stackblitz.io
Maybe add a render method to the class and move the CustomButton outside the class, a working code will help you to find the issue.
Edit: first code example was unclear to me, like others said, probably it's StrictMode. Keep in mind that it will run only in the development environment. For a quick check on your local machine, for example, if you're using create-react-app you can simply run the build command and then serve the app in your browser to verify if you get a double console.log with the prod build.
I'm working on my first project with i18n and I've run into this issue. My client wants a navigation bar with texts expanding depending on the currently viewed section. Something like this:
So for each label I'm using FormattedMessages like this:
<FormattedMessage id="navigation.what"/>
<FormattedMessage id="navigation.how"/>
I get all the strings from .json file.
Now I'm thinking - do you know if there's any way to use .substring on the FormattedMessage?
Also does this approach make any sense or should I just use different strings for expanded and shortened label in .json and be done with it?
<FormattedMessage id="navigation.what"/> component will always returns a span. For getting string from react-intl, you should be using formatMessage() function. You can use it like the below:
Inject Intl using injectIntl higher order component:
import { injectIntl } from 'react-intl';
#injectIntl
class YourComponent extends Component {
...
render () {
...
const {formatMessage} = this.props.intl;
...
<span>{formatMessage(navigation.how).substring()}</span>
Go through this function for more details:
formatMessage()
Usage example
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?
Complete newbie to React and trying to find out how to load the HTML for components rather than inserting it directly in the render method. For example
import React, {Component} from 'react';
export default class Login extends Component {
render() {
return (
<!-- how can I provide a link to the HTML template for here? -->
);
}
}
React does not have HTML. The JSX that you write in the render method is actually compiled into JavaScript. At the core, React components are all JavaScript. The styles are also inline. Componentisation is neat in React because HTML, CSS, JavaScript (interactions) are all in one place, as JavaScript.
To insert raw HTML, React has an attribute dangerouslySetInnerHTML.
<div dangerouslySetInnerHTML={createMarkup()} />
If you want some type of organization, you can use variables to set the html and then assign that to the render functionalty, but React does not use html templates
var hello = React.createClass({
render: yourVariable
});
I think you might be confused about how JSX works.Just in case, I want to clarify that JSX is what they call "syntactic sugar", that turns React methods such as React.createElement into that XML like syntax. For instance:
var Nav;
// Input (JSX):
var app = <Nav color="blue" />;
// Output (JS):
var app = React.createElement(Nav, {color:"blue"});
(from the React docs)
So, to the best of my knowledge, the JSX syntax actually belongs in the render method. If what you are really looking for is the best way to separate and reuse purely presentational code, you should read on separating your app into Container and Presentational components
https://medium.com/#learnreact/container-components-c0e67432e005#.dzjqc8yrn
https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.mn9nf6lz6
Stateless/Presentational/Dumb Components are just functions that return JSX. So you could have your Template component:
import React from 'react';
//you need to import React to use JSX, as it will be expanded into React.createElement calls...
function Template(props){
return (
//...your template here...
);
}
And then your class
import React, {Component} from 'react';
export default class Login extends Component {
render() {
return (<Template {...props}/>);
}
}
}
Makes sense?