Using existing cljs components in a React project? - javascript

https://www.reddit.com/r/Clojure/comments/4el0xi/how_to_use_an_existing_reactjs_component_with/
There is this existing post about using existing ReactJS components in a CLJS/Reagent project. I'm looking to do the opposite. I have a bunch of CLJS components and would like to compile them into a ui library of some sort so that they can be used by React developers. That is, if I have a button CLJS component, I would like to be able to render that Button using < Button /> or mylib.Button(_) etc.. in a React/js app file.
I have read this - https://shadow-cljs.github.io/docs/UsersGuide.html#target-node-library - extensively but it's not quite working out. I've been using ":target :node-library" and I can get simple functions (that return strings/numbers, for example) to compile and work in my app, etc.. but it doesn't work for entire components. For example, my cljs button component takes in :
defn button [props & children]
but when I try to pass in these parameters (I call {lib.button({}, {})} in my App.js file), I get errors like "No protocol method IMap.-dissoc defined", because I'm trying to pass JS objects into CLJS-only functions, I believe. Not sure how to resolve this..
I can explain more on this if it would help clarify. It would also be super helpful if anyone had a reference demo project or any resources they could link me to.

I only have a few suggestions:
You can try to build a new sample project to consume your library with lein new figwheel myproject and use JavaScript interop to move one step at a time closer to the native JS way of using your library.
You can create an interface namespace that can consume JS objects and wrap these into Clojure data structures to sort out the protocol errors you're seeing, eg. functions that take a props parameter and pass down (js->clj props) to the rest of the code underneath.
For the authoritative source, check the Reagent docs, especially this: http://reagent-project.github.io/docs/master/InteropWithReact.html#creating-react-components-from-reagent-components

Related

Visual builder to work with manually hard-coded templates/components

I wonder, is it possible to create a visual no-code builder to work with JS components (e.g. React JSX) if them are manually hard-coded before?
Let me explain what I mean.
Suppose a simple React component pages/index.js previously written by a developer manually:
function HomePage() {
return <div>Welcome to Next.js!</div>
}
export default HomePage
How can we change such a component in the front-end using a visual builder?
For example, we want to add a new HTML element (e.g. H1) inside the existing div.
As I can understand, the builder first needs to know in which JS file the HTML markup is stored to update it. So we can add id="homepage" to the div first and then store a relation as a config like
{"homepage": "pages/index.js"}
And now if we add a new element inside <div id="homepage">, the builder adds the element to the DOM of the div at the client, then takes the whole updated DOM of the div and writes back to the file index.js according to the config
Ok, but the file contains not only HTML markup - it's JS (React) code.
How to keep all the JS code e.g. function HomePage(), return, export default and so on ?
As an option, we can separately load all the JS code as HTML including non-HTML code as #text nodes. Then update the DOM and re-write everything back to the file.
But it sounds complicated and may cause unexpected issues.
So what solution would be the best?
Or maybe there is a ready React-specific solution?
Or maybe it's a bad idea at all to parse and re-write manually hard-coded components by visual builder and the only solution is to store everything as JSON like "homepage":{"div", {"class":""}, "Welcome..."} which is more easy for re-writing ? (but requires a new render)
It depends
I believe the answer that you are looking for very much depends on the level of flexibility that you want your no-code builder to have.
Depending on that, your project could benefit of the trade-offs and advantages of different solutions.
Let's briefly remember that basically a React component will need some props that then will be taken through a render template and output a working HTML. This is assuming a basic case where you don't need your react components to be smarter. Additionally, JSX is just sugar coating over function calls, so you could basically just compose functions to output a React component independently of using the JSX syntax. Hence no need to declare HTML, just changing the output of your no-code tool to JS instead of HTML.
For example, if you can modify how the no-code tool render, you can specify that when moving an element inside another you basically:
Highly Flexible & Customisable
In a highly flexible setup, I will recommend going through the last option you numbered, having a Data-Driven UI is the most common of the cases for complex systems. For example, Figma has an option to export the designs as react components, you can read how they do it here. Basically they take the tag output from figma which is a JSON of tags and create some React componets using templates. If you define "you own UI language" you could have quite a good control over what blocks you can build and define the way of interacting with them (e.g. adding a img component could be quite easy if you know the props and what it needs to render, then creating a React template for it is easy).
Limitations: you require to plan quite well the API of the parser and interaction between different sets of items.
Simple no-code builder
For simpler scenarios you could go with the first approach that you mention, you won't even need to add ids, some tools like React Developer Tools can already inspect the VirtualDOM to understand which part of the render belongs to which React Element (using react internals, which could take some time to understand, but for example you can inspect in the rendered how they use the data-reactid for identification). Knowing this, you can already define the template functions for the render() method (so the JSX output), and separate it code wise, so that when you generate the code, the HTML template is split from the React code as much as possible.
Silly example of how it could look:
// htmlBlockTemplate.js
export const helloPageTemplate = (props) =>
`<div> <h1>${props.title}</h1> </div>` // This can be generated from the `no-code`
// page.jsx
export const Page = (props) => {
return helloPageTemplate(props)
}
Using functions it could look like:
const Page = (props) =>
return React.createElement('div', null,
React.createElement('h1', title: prop.title, `The title ${title}`)
);
}
Limitations: eventho you could, adding custom components (like another React Component or a web component), it becomes more difficult since you will also have to deal with the import graph and probably.
Inevitably you will need to tweak how the render of the component works (rather by creating a parser from your UI language, or changing how the react component is written. If you have a good control of AST, then writing a parser for either of the cases should not be a problem.

Can I use a React app as a component on a static HTML page

I'm new to React and JS, and working with react-csv-viewer.
It works as expected and I can build and deploy it on a local server. But I do not require this, I just want to integrate the app as a component of a static HTML page.
I've tried following the process listed on the React tutorial for this, but I have trouble understanding the build process and how can I achieve this.
All I wish to achieve is to be able to use <CsvViewer /> provided by the author, possibly like this
const rootElement = document.getElementById("root");
ReactDOM.render(<CsvViewer />, rootElement);
and get the viewer app rendered at my HTML file, without building and deploying the viewer app on a (local) server.
Will appreciate any help or hints in this regard.
You can add React as it was shown in the tutorial you linked. The downside is that, you can't use JSX syntax (as it should be converted to JS during build time as it's not recognized by browsers as so).
Here is a post explaining how you can do so without transpilaton steps.
https://codepen.io/alexkrolick/post/react-without-a-build-step
Alias React.createElement, and call it to create components.
e.g.)
const h = createElement // convenient alias
// Instead of
<div className="foo" />
// create an element like so
h("div", { className: "foo" })
For more info on how that works, check out the official documentation.
https://reactjs.org/docs/introducing-jsx.html#jsx-represents-objects
But I really doubt anyone writes React code that way without a transpilation step in real life.
Would creating a separate site/page with React be a problem by chance? You can check out ParcelJS to easily create a React site if you aren't familiar with transpilation.

Using javascript workflow library within mean stack project

I have developed a web app which is a QA forum using mean stack approach. Currently the project is working and I have implemented the basic requirements like login authentication using passportjs, then storing questions, answers, votes etc. in mongodb using mongoose.
Now I am required to add a state machine like workflow programmatically to the entire project where each module (eg.login module) will act as a state. And a flow for them must be defined.
I have looked into javascript workflow engines like workflow-4-node, bpmn.js, turbine.js. So my question is, how should I use these libraries without changing any code of my project, Is there any specific approach to do this, or am I required to change my entire code to implement the work flow.
Also in my project I am using ui.router(Routing module for angularjs) to switch between different pages and controllers (by using $stateProvider). So is this routing that I have implemented, and the state machine like workflow that I am required to do, same(different terminologies but same concept) or are they different?
NoFlo 0.8 provides a asCallback interface, allowing users to embed NoFlo graphs into existing JavaScript code.
So, if you have defined a NoFlo graph for a particular workflow, you can include it to your JavaScript app like this:
// Wrap a NoFlo graph
var myFunc = noflo.asCallback('my-project/MyGraph');
// Call the wrapped graph
myFunc({
inport: 'data'
anotherport: 'more data'
}, function (err, result) {
// Do something with the result
});

Using an external React component on Rails application

I am trying to use the rc-slider React component on a existing Rails application that is using react-rails gem and it already have some other components that were built within the application that work just fine.
Based on this blog post I've been able to follow its first 3 steps, I've found the minified and browser-ready version of it here, added the file to the suggested path and required it on the application.js as recommended but even seeing the code within the Sprockets generated application javascript file that is rendered on the browser I can't see or use the supposed global variable it would provide according to step 4.
In the component's examples page it uses a const Slider = require('rc-slider'); statement in order to get that available. I've tried that but without luck as it throws: Uncaught ReferenceError: require is not defined. The same happens when I try the README usage's section approach: import Slider, { Range } from 'rc-slider';. I've tried both from an existing JS where I load other React components and also from the browser's Dev Tools Console window.
Am I using the wrong approach to the problem or maybe missing/overseeing any concept or basics here?
If you want to use Sprockets, you can get a pre-compiled version of rc-slider from unpkg:
https://unpkg.com/rc-slider#6.0.0/dist/rc-slider.js
Taking a look at the source, I see it exports the library as rc-slider:
So you can access it as window["rc-slider"] and use it from there, for example:
var RCSlider = window["rc-slider"]
var container = document.getElementById("container")
ReactDOM.render(
<div>
<RCSlider />
<RCSlider.Range />
</div>,
container
);
jsfiddle
That way, if you put rc-slider.js in the asset pipeline, you can use RCSlider in your javascripts.

Generate components in sub-folders in ember/ember-cli

Based on recommendations for the preparation for Ember 2.0...
• In general, replace views + controllers with components
• Only use controllers at the route level...
...we're supposed to eschew Controllers and Views in favor of Components. I haven't been able to figure out and/or understand how to generate Components that aren't direct parents of the components folder, i.e. components/component-name.js.
My current controllers folder looks something like:
/controllers
/account
index.js
edit.js
/business
index.js
Basically, there are sub-folders that group logic based on the sections of the application. How do I accomplish this with just components?
Seeing that components must have a "-" in them, I tried, but get an error...
ember generate component account/index-module.js
You specified "account/index-module.js", but due to a bug in Handlebars (< 2.0) slashes within components/helpers are not allowed.
Do all components have to be like
components
account-index.js
account-new.js
business-index.js
i.e. all in the same folder? This will start to get out of hand with the addition of what I actually consider to be components (things like video-viewer.js, text-editor.js, radio-button.js).
I would really like to have components in sub-folders, but unsure how to do this.
components
/media
/audio
audio-player.js
/video
video-player.js
/text-editing
text-editor.js
editor-toolbar.js
My components folder is already gross and I just got started:
Is it okay to leave the account/business logic in Controllers (seeing that it does say you should only use controllers at the Route level)?
I'm really confused about this "all components, all the time" convention.
Ok, so I had the same problem and as of ember 1.9-beta.3 (that's the version I tested). It is possible to have components nested under resource directories.
That means that you can have a "user" route or resource. And let's say you have a component which you only want to use with the user resource, so you want to put the component under the resource directory.
The way to do it is to put the component under the resource directory app/pods/user/component-name/template.hbs. The important part is to remember that components must have a dash in their name. It can't be just .../user/component it has to be .../user/component-name with a dash. Then you can use the component as {{user/component-name}} in your templates.
Also I think this is only possible when you're using the pod structure.
Ok, I think this question/answer needs a bit of an update for 2019. I have been using Ember for all of about a month, and my components folder has already become a pigpen. And the tutorial and main API docs don't really cover how to organize your components.
So I did a search of course. And the only answers I could find (like this one) are from around 2014-2015, and don't reflect modern Ember. I was about to accept my fate when I found this in the Ember syntax conversion guide.
(Note to the Ember folks: This is an important issue, one that almost every new user will encounter. It should feature a bit more prominently in the documentation. Maybe not the tutorial, but definitely in Components section)
You can in fact generate components under a sub-folder in Ember as such:
$ ember generate component foo/bar-baz
installing component
create app/components/foo/bar-baz.js
create app/templates/components/foo/bar-baz.hbs
installing component-test
create tests/integration/components/foo/bar-baz-test.js
So that's great, the files are created under components/foo and templates/components/foo. And to resolve the name of the component for use in another template, you can use either the old style syntax:
{{foo/bar-baz }}
Or the new style angle bracket syntax:
<Foo::BarBaz />
As the assertion suggests this is due to Handlebars 1.x, and will be available soon.
Ember 1.9 beta builds currently support this, though I'm not positive if ember-cli's resolver would work with it right now. You can read more about Handlebars 2.0 here.
Using a pods structure will also help with organization, and I believe is going to be the recommended strategy going forward.
For now, I'd suggest not to worry about it! Remember the transition plan will be smooth, and as the official releases come out for Ember and Ember CLI, you'll get deprecation warnings.

Categories

Resources