Can I give arguments to a react-app? (dependency injection with React) - javascript

I would like to use a React-App, and give it some arguments (props), depending on where I embed it.
So one step back, we are using React actually as a library, and not the entire page is in React. We have a very functioning website, and some parts are now being build in react. Our motivation is: If you want the same component in another page, you can simply copy-paste 3 lines which include the css and js files, put a <div id="myReactAppRoot"></div>, and that's it. Very quick, very clean, and instantly functioning.
My question
When I have another "copy" of the React app, I would like to give it a different starting state.
One example use-case: I have two pages, in one I want the data to be grouped by X and in the other grouped by Y.
Another use-case, which I will have on my next project: disable editng, depending on the users permission level (the permission level is known by the main page).
How can I achive this?
My current solution
My current solution is simply having a utils.js in the React app, which I use to access the windows object and get out the pieces I want:
const utils = {
fun1: window.myProject.forReact,fun1,
groupElements: window.myProject.forReact.groupElements,
permissionLevel: window.myProject.forReact.permissionLevel
};
export default utils;
Then importing utils in other components and using the functions/reading the values. And of course making those objects available on the main page.
But really, this feels wrong.
My ideal solution would look a lot like the Vue.js way:
<div id="app">
{{ message }}
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
Because I can just copy paste this bit, and change the Hello Vue!, and all the sudden the starting state is different in my "second copy" of it. Or even more cleverly, wrap it in a function that gets some initialState and put that JavaScript part in a file which I reference.
I have considered
I have considered editing the compiled JavaScript code that is being referenced. So far I only saw that the actual hooking into the myReactAppRoot-element is being done in the main.chunck.js, and editing that file seems too much like a hack (feels more wrong than my current solution).

To expand on Mike's comment, let's first translate your Vue app into React:
//html
<div id="root"></div>
//JS
const App = ({message}) => <div>{message}</div>
const rootElement = document.getElementById("root");
ReactDOM.render(
<App message={"Hello, React!"}/>
rootElement
);
A function that mounts an instance of App on a DOM node with id domId would be something like
function mountAppWithMessageOnNode(message, domId){
const rootElement = document.getElementById(domId);
ReactDOM.render(
<App message={message}/>
rootElement
);
}

Related

Call a function on a react child functional component from parent

I have a very large and complex React application. It is designed to behave like a desktop application. The interface is a document style interface with tabs, each tab can be one of many different type of editor component (there are currently 14 different editor screens). It is possible to have a very large number of tabs open at once (20-30 tabs). The application was originally written all with React class components, but with newer components (and where significant refactors have been required) I've moved to functional components using hooks. I prefer the concise syntax of functions and that seems to be the recommended direction to take in general, but I've encountered a pattern from the classes that I don't know how to replicate with functions.
Basically, each screen (tab) on the app is an editor of some sort (think Microsoft office, but where you can have a spreadsheet, text document, vector image, Visio diagram, etc all in tabs within the same application... Because each screen is so distinct they manage their own internal state. I don't think Redux or anything like that is a good solution here because the amount of individually owned bits of state are so complex. Each screen needs to be able to save it's current working document to the database, and typically provides a save option. Following standard object oriented design the 'save' function is implemented as a method on the top level component for each editor. However I need to perform a 'save-all' function where I iterate through all of the open tabs and call the save method (using a reference) on each of the tabs. Something like:
openTabs.forEach((tabRef) => tabRef.current.save());
So, If I make this a functional component then I have my save method as a function assigned to a constant inside the function:
const save = () => {...}
But how can I call that from a parent? I think the save for each component should live within that component, not at a higher level. Aside from the fact that would make it very difficult to find and maintain, it also would break my modular loading which only loads the component when needed as the save would have to be at a level above the code-splitting.
The only solution to this problem that I can think of is to have a save prop on the component and a useEffect() to call the save when that save prop is changed - then I'd just need to write a dummy value of anything to that save prop to trigger a save... This seems like a very counter-intuitive and overly complex way to do it.... Or do I simply continue to stick with classes for these components?
Thankyou,
Troy
But how can I call that from a parent? I think the save for each component should live within that component, not at a higher level.
You should ask yourself if the component should be smart vs dumb (https://www.digitalocean.com/community/tutorials/react-smart-dumb-components).
Consider the following:
const Page1 = ({ onSave }) => (...);
const Page2 = ({ onSave }) => (...);
const App = () => {
const handleSavePage1 = (...) => { ... };
const handleSavePage2 = (...) => { ... };
const handleSaveAll = (...) => {
handleSavePage1();
handleSavePage2();
};
return (
<Page1 onSave={handleSavePage1} />
<Page2 onSave={handleSavePage2} />
<Button onClick={handleSaveAll}>Save all</button>
);
};
You've then separated the layout from the functionality, and can compose the application as needed.
I don't think Redux or anything like that is a good solution here because the amount of individually owned bits of state are so complex.
I don't know if for some reason Redux is totally out of the picture or not, but I think it's one of the best options in a project like this.
Where you have a separated reducer for each module, managing the module's state, also each reducer having a "saveTabX" action, all of them available to be dispatched in the Root component.

How to create inject React components from XML

Imagine you made a web framework that helps you quickly make blogs for clients. For the sake of this post, its the same blog template everytime, what changes is the content. You're React app is a simple structure of the following [where the Content state is just changing each time]
<App>
<Navigation/>
<Content/>
</App>
What makes the framework is you have XML files which contain the HTML. Each XML file represents one blog post. The app pulls all the HTML from the XML files, and puts it into the state of the App in a "blog posts" array. Depending on the state of the app, a specific entry in the array will be displayed in Content...
Content's state has a field called "html" which is what holds the HTML to be injected in string form. [you have to use dangerouslySetInnerHTML]
This concept works fine, and I have a version of it now. However, imagine you have a React components that you want to add to each blog post. Say you want to add the component into a specific blog post in a specific section. You want to add props to it and such. Now this goes out the window with dangerouslySetInnerHTML
This is where I am stuck trying to find the best direction to go. The only thought I have now is the following:
Since you would now be writing JSX in the XML, just make each blog post its own component. You would have ...etc and then if this.state.currentPost === 1 then display BlogPost1 and likewise. Yet you would have to have a huge block of if-statements depending on how many blogposts you have, and its not ideal to have to add everytime you have a new blogpost
When I read the title of your question I got curious and found this library to parse XML into React components: xml-to-react. But that's not what you are asking for.
As you want to use components in the middle of you string of HTML, I'll suggest: react-remarkable. This component compiles its children (a string with markdown/html/react) into react nodes.
Example from its docs:
var React = require('react');
var Markdown = require('react-remarkable');
var MyComponent = React.createClass({
render() {
return (
<div>
{/* Pass Markdown source to the `source` prop */}
<Markdown source="**Markdown is awesome!**" />
{/* Or pass it as children */}
{/* You can nest React components, too */}
<Markdown>{`
## Reasons React is great
1. Server-side rendering
2. This totally works:
<SomeOtherAmazingComponent />
Pretty neat!
`}</Markdown>
</div>
);
}
});

is there such a thing as JSX 'partials'?

I work mainly with Handlebars JS now, but I am looking at JSX. Is there a JSX equivalent to Handlebars partials? I want to know if I can create small bits of markup that I can reuse in several different JSX views.
It doesn't provide partials. Some things about React:
React doesn't provide any notion of partials. The fundamental, atomic unit of React is the component.
Instead of passing a partial, you'd create a component or components and re-use those. Even better than a partial because it's a function, so it's encapsulated and testable!
If the markup is small, it should probably either be moved up into a parent component or down into a simpler one
Generally, my rule of thumb is that components should follow the principle of single responsibility or separation of concerns. If something doesn't seem to fit into a component, you've likely got problems in the other two components and could reconsider them, too :)
Another couple rules of thumb to go by when thinking about components:
code smells should usually end up as components (repeating something over and over again, etc.)
components are usually either presentational or containerized. The latter have roles in the props/state tree for an app (you never "see them")
refactor things into components as you need to; don't start out encapsulating everything, because you may have prematurely refactored and created more problems for yourself
the most reusable and decoupled components are like the best functions or objects: clean, flexible, testable, and they do address a single concern
at the same time, don't go crazy and turn everything into a component. i.e. you don't (usually) want:
<Letter>R</Letter><Letter>e</Letter><Letter>a</Letter><Letter>c</Letter><Letter>t</Letter>
Here's an incredibly simple example:
'use strict';
const OuterComponent = React.createClass({
render() {
return (
<div>Outer{this.props.children}</div>
);
}
});
const ReusableComponent = React.createClass({
render() {
return (
<div>Am I reusable? {this.props.reusable && 'Yeah!' }</div>
);
}
});
ReactDOM.render(
<OuterComponent>
<ReusableComponent reusable={true}/>
</OuterComponent>,
document.getElementById('container')
);
Will render:
OuterComponent
Am I reusable? Yeah!
Note, though, that using creatClass provides you more than you might need if you're not working with mutable state (which is provided to you within the component via this.state), you can easily use what are sometimes called "stateless functional components" (because they are, well, stateless and returned by functions). These could easily be arrow functions implicitly returning the JSX (which is essentially just React.createElement() generator)
const OuterComponent = (props) => <div>Outer{this.props.children}</div>;
const ReusableComponent = (props) => <div>Am I reusable? {this.props.reusable && 'Yeah!' }</div>;
ReactDOM.render(
<OuterComponent>
<ReusableComponent reusable={true}/>
</OuterComponent>,
document.getElementById('container')
);
Just create a component for that. Components can be as simple or as complex as you want them to be.
Example:
function Badge(props) {
return <span className="badge">{props.counter}</span>
}
With a corresponding .badge CSS class, this could be a very simply component that renders as a red circle with a number, and is used as <Badge counter={42} />.

React.js: Is it possible to namespace child components while still using JSX to refer to them?

So let's say I have a component called ImageGrid and it is defined as below:
window.ImageGrid = React.createClass({
render: function() {
return (
<div className="image-grid">
<ImageGridItem />
</div>
);
}
});
As you can see it includes a child react component called ImageGridItem. Which is defined below.
window.ImageGridItem = React.createClass({
render: function() {
return (
<div className="item-container">something</div>
);
}
});
This works fine as long as both are directly properties of window. But this is kind of horrible so I'd like to group up all my react components under a namespace of window.myComponents for example.
So the definitions change to:
window.myComponents.ImageGrid = React.createClass({...});
window.myComponents.ImageGridItem = React.createClass({...});
The problem now is that as ImageGrid refers to <ImageGridItem /> in it's render() function, the JS version of this gets compiled out to JS as ImageGridItem() which of course is undefined since it's now actually myComponents.ImageGridItem() and react complains it can't find it.
Yes I realise I can just not write JSX for that component include and manually do myComponents.ImageGridItem({attr: 'val'}) but I'd really prefer to use the JSX html syntax shortcut as it's much easier to read and develop with.
Are there any ways to get this to work while still using the <ImageGridItem /> syntax for children? And if not is it possible to define the JS namespace within the JSX?
This pull request was just merged:
https://github.com/facebook/react/pull/760
It allows you to write things like <myComponents.ImageGridItem /> in React 0.11 and newer.
That said, a proper module system is the recommended way to manage dependencies to avoid pulling in code that you don't need.
Currently, there isn't a way to do this. Namespacing with JSX is on the todo list.
Most people use some kind of module system (browserify, webpack, requirejs), which replace namespacing and allow components to be used easily. There are a lot of other benefits, so I very much recommend looking into it.

What are the difference/similarities between React (app framework from Facebook) and react.js (reactive extensions for JS)?

I recently learned about Facebook/Instagram's app framework for JavaScript called "React" and wanted to look more into it. However, I found myself getting conflicting search results, as there is another library of a similar name. So, my question is this: Are there similarities between the two, or could someone do a better job at naming?
React
http://facebook.github.io/react/index.html
react.js
http://www.reactjs.com/
react.js is a language extension that lets you have automatic binding for values. The name React comes from the automatic updates of the values when one changes.
react( "soonChanged = undefined" );
react( "reactive = soonChanged + 5" );
react( "reactive2 = reactive * 10" );
react( "soonChanged = 10" );
// Changes the value of reactive from "undefined5" to 15
// and of reactive2 from NaN to 150
React on the other end is a framework to build user interfaces. The name React comes from the automatic update of the UI when some state changes.
/** #jsx React.DOM */
var converter = new Showdown.converter();
var MarkdownEditor = React.createClass({
getInitialState: function() {
return {value: 'Type some *markdown* here!'};
},
handleChange: function() {
this.setState({value: this.refs.textarea.getDOMNode().value});
},
render: function() {
return (
<div className="MarkdownEditor">
<h3>Input</h3>
<textarea
onChange={this.handleChange}
ref="textarea"
defaultValue={this.state.value} />
<h3>Output</h3>
<div
className="content"
dangerouslySetInnerHTML={{
__html: converter.makeHtml(this.state.value)
}}
/>
</div>
);
}
});
React.renderComponent(<MarkdownEditor />, mountNode);
A bit more comparison added to above:
react.js
can also do auto UI updating, but you need to manually code that:
/* **syntax aren't correct but the idea eg:
(you can find it in their doc for correct syntax) */
react( "yourReactiveComponent = 1" )
react( "$('body').html( yourReactiveComponent )")
/* now u change that variable */
react( "yourReactiveComponent = 4" )
/* it will automatically call that jquery function to change the html from 1 to 4 */
it is not really a framework, just an PUBSUB event helper, that subscribe and publish on variable change
awesome for small applications
facebook React
this is a framework
they will deal with a lot of cross browser issues
they have stuff worked on optimising performance such as an virtual DOM
has their own cool markup syntax compiler JSX and JSXtransformer, so you can write declarative HTML in a JS file and than transform it into a real JS file
they are component focus, so you will have both js and html that related to one component managed within their own code block, making it so much easier to change DOM stuff without switching all the time from JS to TPL and vice versa, This is the part where i love the most, I've been coding like this for some time, but never have a framework that does this for me, now I do :)
now http://www.reactjs.com/ redirect to https://facebook.github.io/react/
It's domain seems to be acquired!
at this time 2016-08-23, the google search result of react.js are all about facebook react
i don't know what you said react.js is, it seems disappeared!
from the answer above
react.js is a language extension
i just think it seems that the old react.js is now http://reactivex.io/, i don't know right or wrong
you can see some comparison here: http://blog.getsetbro.com/js/FB-react-vs-reactiveJS-vs-ractiveJS-vs-reactiveUI-vs-reactiveX.html

Categories