Does 3d.io support React components at future ? Now, I need to find dom element utilized "ref" from component to retrieve io3d objects.
render () {
// this.props.elements is the state from getAframeElements
if (this.props.sceneId !== '') {
this.props.elements.forEach( (item) => {
this.refs.scene.appendChild(item)
})
}
return (
<a-entity ref="scene">
</a-entity>
)
}
Do you have any guides how to use 3d.io at React project ? Or I need to use document.querySelector after componentDidMount event at React.
A few things here:
How to use react and 3d.io
Most 3dio-js methods return plain js objects and arrays that you can use with any javascript library.
Here's how you could use io3d.furniture.search in a react component: https://jsfiddle.net/wo2xpb9g/
How to combine react and a-frame
There is the aframe-react project that will make combining a-frame and react easier https://github.com/ngokevin/aframe-react
As of newer versions of react it seems possible to combine a-frame and react directly like you've done, here's an example: https://codepen.io/cassiecodes/pen/akXWjo?editors=1010
How to use io3d.scene.getAframeElements with react
getAframeElements is a convenience method which converts sceneStructure into real a-frame DOM nodes. In react projects, real DOM nodes are generated by react itself.
There are two possibilities,
Instead of getAframeElements, convert sceneStructure from io3d.scene.getStructure into react virtual DOM yourself. Hopefully a community library will be published for this soon.
Keep the a-frame DOM separate from react. This is the approach sometimes used to combine react with libraries such as D3, which directly manipulate the DOM... that approach is discussed with examples here: https://medium.com/#Elijah_Meeks/interactive-applications-with-react-d3-f76f7b3ebc71
Related
I'm using react-rails to add some react componenets to an existing ruby on rails app. I just realized that all the props being passed initially to the component are easily seen if you inspect the component
<%= react_component('ProfileWeeklyWriting', {
languages: #user.languages,
currentUser: #current_user,
responses: #writing_responses,
clapLottie: asset_url('lottie/clap.json'),
clapIcon: asset_url('icons/clap.svg'),
arrowIcon: asset_url('icons/arrow_green.png')
}) %>
But when you inspect the element, allll those variables are shown!
I know I can just do an ajax call from within the component, but is there a way to pass variables to the component initially, without them being shown to the world?
Let's take a bit theory about how it works. When you do classic SPA without any backend engine you usually do something like
ReactDOM.render(<App />, document.getElementByID('root'))
Which simply render the root component on place of <div id="root" />. When you apply Rails templates on the top, you are connecting 2 different worlds. ReactDOM and Rails slim templating engine (probably) but they don't know nothing about each other. ReactRails is really simply routine which does something like this:
1 Inject custom react-rails script to page
Wait for DOM ready
Collect all [data-react-class] elements
Iterate through of them and call ReactDOM with props.
You can think of it like calling several "mini apps" but in fact those are only components (react doesn't distinguish app/component, it's always just a component)
So the code is something like this (I didn't check the original code but I wrote own react-rails implementation for my company)
function init () {
const elements = document.querySelectorAll('[data-react-class]')
if (elements.length > 0) {
Array.prototype.forEach.call(elements, node => {
if (node) {
mount(node)
}
})
}
}
function mount(node) {
const { reactClass, reactProps } = node.dataset
const props = JSON.parse(reactProps || '{}')
const child = React.createElement(window[reactClass], props)
ReactDOM.render(child, node)
}
Then the DOM ready
document.addEventListener('DOMContentLoaded', e => {
init()
})
Son in fact Rails doesn't know anything about React, and React doesn't know anything about Rails unless it's not living on window. (THIS METHOD IS HIGHLY DISCOURAGED.
In real world there are ways how to make "server" rendering, which means that this piece of code is done on server to not expose props and whole React lifecycle and just flush real prepared HTML to DOM. That means that in the lifecycle BEFORE HTML is sent to the client, there is called transpiler which compiles those components, you can read about it here
https://github.com/reactjs/react-rails#server-side-rendering
So it just calls those methods with a help of https://github.com/rails/execjs
So the only way how to "not expose" props to the client is to "pre-render" components on backend by some engine (either some JS implementation for your language or directly node.js backend). I hope I gave you a better picture how it works and how it can be solved!
I have noticed that certain libraries such as classnames are readily available in Preact but others like styled-components require preact-compat.
What makes a React library unsupported natively in preact that it requires the use of preact-compat?
Disclaimer: I work on preact.
There are several APIs in react that are not needed for preact. But because existing third-party libraries have been developed for those APIs we published preact-compat which re-implements them on top of preact.
Some examples:
Children-API:
This API is in particular interesting because it isn't needed at all for preact. With preact the children property is always an array.
// React
Children.forEach(props.children, child => ...);
Children.map(props.children, child => ...);
Children.count(props.children);
// Preact
props.children.forEach(child => ...);
props.children.map(child => ...);
props.children.length;
unmountComponentAtNode:
This is another API that is not needed for preact, because we can simply unmount any tree by rendering null:
import { render } from "preact";
import App from "./app";
// Render App into dom
render(<App />, document.getElementById("root"));
// Unmount tree
render(null, document.getElementById("root"));
If you want to drop a subtree instead of the root node you can do that via returning null from a component. Basically null is always treated as an empty value.
findDOMNode:
// React
const element = React.findDOMNode(componentInstance);
// In Preact that's just a property
const element = componentInstance.base;
In our case this even works for function components. Note that in nearly all cases refs are preferred over findDOMNode.
Summary: preact-compat contains mostly shims for third-party libraries expecting full API compatibility with react.
I am trying to learn component based frameworks for frontend apps. Currently, I am using RiotJS but it applies to any framework that uses the same concepts (React, Angular 2.0 etc).
In a basic MVC frontend frameworks (e.g AngularJS), the controllers and router were very connected to each other. But with a component based framework, the line between router and controllers is much wider. And this is what confuses me the most.
Here is one example of an app that I am trying to build:
I have three main UI elements: Navigation Bar, Content Area, and Signin Form. So, I created three components: my-navbar, my-content, my-signin. I was able to create multiple routes per component. So for example, if there is a route changes, the navbar updates the active "module." Making this was easy because all I am doing is changing class of a list item.
Now, I want to load other tags inside <my-content></my-content>. In AngularJS, I was always changing the view completely (using ui-router). How can I achieve that in a component based framework. Let's say that I have 2 more components called my-content-users-list-view, my-content-users-detail-view. How can I add them to the component my-content based on the route? Do I just add it like document.innerHTML += '<my-content-users-list-view></my-content-users-list-view>?
I know most of my syntax is RiotJS but I will understand it if you write it in another framework's syntax.
Thank you!
Essentially, yes, you could just append your tag as a DOM node and then call Riot to mount it:
riot.route('/awesome-route', () => {
const tag = 'your-awesome-tag';
const options = { ... };
const elem = document.createElement(tag);
// TODO empty your content container using pure DOM or jQuery to get rid of the previous route's view...
document.querySelector('#content').appendChild(elem);
riot.mount(elem, tag, options);
});
Let's say i have a React Component <forecast id="test"/>. And i want import this component into a legacy project which only have jquery involved.
Is it possible to get the value of this component like document.querySelector('#test').value?
I got some information from React website, that we cannot access data from outside the component. The recommended way is dispatching data from inside of the component.
My question is, the way to dispatching data is behind of the component implementation. Is it means that i have to read the source code of component in case i don't know how it works?
If this is true, i won't think React is free to inject to any product, it cost too much.
If you want to inject some React to your project you should do it with some independent part of your system.
If you have tightly coupled code base its always high cost to add any new technology to it. So its not a React problem. Try to find some independent module or subapplication in your system and move it to React. If you cannot find one, try to refactor existing code first.
You need to write a plain JS wrapper to do it. Something like this might work
function Forecast(element) {
this.value = initialValue;
React.render(<forecast onChange={onChange.bind(this)}/>, element);
function onChange(newValue) {
this.value = newValue;
}
}
I'm trying to use react-router in my Clojurescript Reagent project. The problem is, react-router requires that components pass React.isValidClass(component), which in React 0.11.2 is defined as:
ReactDescriptor.isValidFactory = function(factory) {
return typeof factory === 'function' &&
factory.prototype instanceof ReactDescriptor;
};
Reagent seems to generate components as an object instead of a function. Here is my code:
(defn home []
[:div [:h1 "Home Page placeholder"]])
(reagent/as-component (home)) ; => #<[object Object]>
Has anyone worked out how to make this sort of interop work?
What reagent-react-router does to make this work is use reagent.core/reactify-component. The reactify-component exists to make Reagent components valid React components for these kinds of inter-op scenarios.