I recently started on React and I'm using it in combination with Laravel as I would like to replace my jquery by react on a step by step migration.
In my tests, the render instructions are always packaged in the component .js file like this :
ReactDOM.render(<Calculator />, document.getElementById('tutorial'));
and the div <div id="tutorial"></div> is placed in a view.
My problem is that the view is dynamically generated by my php code and sometimes I need to render several component in one page so this approach is not working. Hence I would like to trigger the rendering from the view so something like :
<div id="tutorial" intruction_to_render_calculator_component_in_this_div></div>
How can I do that ?
been all over it recently in trying to find a solution... So here is the one I found :
In my component I put a loop to screen all elements asking to be mount based on an rComponent attribute :
var divs = document.querySelectorAll("[rComponent='Calculator']");
if (divs.length > 0) {
//document.querySelector("[rComponent='calculator']");
for (var i = 0; i < divs.length; ++i) {
ReactDOM.render(<Calculator />, divs[i]);
}
//ReactDOM.render(<Calculator />, document.getElementById('tutorial2'));
}
In my view I just need to put a rComponent in my div :
<div id="tutorial" rComponent="Calculator"></div>
<div id="tutorial2" rComponent="Calculator"></div>
pretty happy with this way of working though I think it might slow the scripts high time
Related
I grab content from a CMS via Gatsby. Inside the markup there are placeholders which should be replaced with React elements.
So I get sth like this:
let content = '<span>Hello World [placeholder]!</span>';
and in React I want to change it to sth like this (where the markup for the tooltip comes from a React element):
let content = '<span>Hello World <div class="tooltip">Important warning</div>!</span>';
The final html with the replaced elements should be dumped into the DOM using dangerouslySetInnerHTML.
I tried using react-string-replace:
reactStringReplace(content, '[placeholder]', () => (<Tooltip />));
but it gives me an array containing a mix of strings and React elements that can't be concacenated without breaking the HTML structure.
What would be a good approach to tackle this issue? Or am I wrong using placeholders in the CMS altogether?
i found a really good npm package that provides this functionality and much more: https://interweave.dev/
I've a multiple page site. I created a single component enclosing all the texts/para/images. I've refered this component to all the multiple pages. I used a class name to hide/show the content to the respective pages via css. Problem is that the page load is slow. Since all contents are hidden using css they are still loaded making my site slow. Any help on this is much appreciated. Thanks
There are multiple things you can check.
Check the internet connectivity, I hope you have good internet connectivity to load the
page.
As you say there are multiple page with single component, check if you can move those into sub-component.
I am not sure how you're hiding those components use css property display:none if those are light weight.
you can use something like this:
<style type="text/css">
.hidden { display:none; }
</style>
render: function() {
return (
<div className={this.props.shouldHide ? 'hidden' : ''}>
This will be hidden if you set <tt>props.shouldHide</tt>
to something truthy.
</div>
);
}
// or in more modern JS and stateless react
const Example = props => <div className={props.shouldHide}/>Hello</div>
source
If I have lets say App component, like this
const App = () => {
return(
<div>
<p>hello world</p>
</div>)}
can I name div whatever i want like I did below? It works in the browser just fine but Im not sure,
const App = () => {
return(
<whatever>
<p>hello world</p>
</whatever>)}
Yes You can. But:
if You want to work with React, don't capitalize the name of div like this: <Whatever>, because it will seems to React that this is an another Component.
And when Your project gets bigger, it will start to get more complicated, so its a good practice to write tags by they names.
Yes you can name them whatever you like, people often do it so the markup is a bit more friendly to read and understand. For example Appcues injects their widget into your website and if you look at the markup for it, it has elements like <appcues/>.
Just check the browser support for these custom HTML tags, I think most major ones do support it but just to be safe.
I'm trying to dynamically load the TokBox embed script in my React app when the user clicks a button. The script tag is being added to the DOM and successfully loading but it does not go on to download opentok.min.js and thus the video control never renders. Adding the code directly into index.html works fine however. What is different about loading the tag dynamically?
Snippit:
import Script from 'react-load-script';
...
render() {
return (
<div>
...
<div id="otEmbedContainer" style={{width:"300px", height:"300px"}}></div>
{this.state.showVideo &&
<Script
url='https://tokbox.com/embed/embed/ot-embed.js?embedId=MYEMBEDID&room=' + this.state.roomId
/>
}
</div>
)
);
Response from TokBox support:
It is noted that when you load embed dynamically. you need to fire following event also after the dynamic loading( this is required for embedded to be loaded as per current design).
var DOMContentLoaded_event = document.createEvent("Event")
DOMContentLoaded_event.initEvent("DOMContentLoaded", true, true)
window.document.dispatchEvent(DOMContentLoaded_event).
I haven't tried this because I switched to use the iframe solution for now but posting here for continuity.
I'm new on React (I more at ease w/ jQuery or AngularJS). I have a special case and I don't find a good way to resolve it...
My app contains an area which is like a "document viewer". It loads an HTML content from the backend (via API, using Fetch) and inject it in the "viewer" component. The HTML content loaded looks like an "university report" (it's just a formatted text, only <span> and <p> with class="..." attributes, nothing more).
Ex : <p>Lorem ispum <span>some text</span> loreb bis <span>ipsum</span></p> ...
I load the content, and inject it this way in the render() of my component <Viewer> :
<div dangerouslySetInnerHTML={ getFreshlyLoadedHTML() } />
Easy, it works just fine !
But... Now, I want to inject some "interactive" components in the loaded HTML. For example, some button to give a feedback etc. The API must decide where to place the component between the words/nodes of the formatted text (HTML).
Ex :
<p> Lorem ispum <span>some text</span>
loreb bis <span>ipsum</span>
<MyFeedbackButton paragraph="1.3"/>
</p><p>Other Lorem Ipsum<p><span>...</span>
There, I'm stucked because I cannot use dangerouslySetInnerHTML if there are components inside the loaded HTML...
First attempt : I've tried modifying the API, and instead of sending the HTML in a string to the app, I send a custom JSON structure that represents almost the final JSX structure that I want. Then, in my react page, the render function only have to parse the JSON and build the JSX (here, a JsFiddle example if it's not clear : https://jsfiddle.net/damienfa/69z2wepo/34536/ )
It works, but I can't believe it's the good way...
I see a major problem : all the HTML node (span, p...) that I build from the render function are referenced by reactJs, is it really necessary ? Mostly, there are "dead" nodes (I mean, dom node that won't never changed, this is static formatted text).
Just take a look a all those "data-reactid" on nodes that never will be interactive...
What would be your advice on that case ?
What about my attempt with a JSON-structure sent by the API ?
Is there a way to say to react "do not reference that element" ?
Do you clearly see a better solution to my problem ?
Your current workflow is not very secure and subject to many potential errors and open doors, especially concerning code injection ...
The overload due to react tracking the nodes is not an issue, React could track 10 000 nodes and not have a problem (well actually on many of my apps React has more than 100 000 nodes to care about and it still rurns perfectly).
I see different solutions here:
If there are only 3 or 4 possibilities of dynamic components and order, you might have components like "templates" to which you would simple send text arguments. This is the safest and easiest option.
If it doesn't suit your use-case but the JSON file can contain only a limited set of components, the components should be located in your main app, and then rendered with custom props from the JSON. Actually given the structure of data you could consider using xml instead of json and build a xml tree that you would parse and render. Only components from your white list would be rendered and it would limit drastically the potentials security issues. If needs quite some work on the XML parser though.
If the JSON file can contain many many different and unpredictable components or if the behaviour of those components is largely dynamic and independant of your app, you might as well consider using an iframe, with its own JS and HTML, so that this part of the code is isolated from the rest.
Try using an inline anonymous function within the inner content from within React using JSX. It works! Just be careful about how you wire up the data so there isn't a route where a user can inject HTML from an input or text field.
<div className="html-navigation-button">{(() =>
{
const CreateMarkup = ( sNavItemName :string ) => {
return {__html: sNavItemName };
}
var sTextToAddHtmlTo = props.nextNavItem.name.toString();
sTextToAddHtmlTo = sTextToAddHtmlTo.replace( "/", "/<wbr>" );
return (
<div dangerouslySetInnerHTML={CreateMarkup( sTextToAddHtmlTo )} >
</div>
);
})()}
</div>
I didn't override the React internals of 'render()', but only used a React Component with props wiring to pass down data to it for rendering.
I added the hook for 'dangerouslySetInnerHTML' deep within the return content of the React Component so there would be no easy way to intercept and manipulate it.
As such, there is no 100% guarantee on safety, but that's where adding good security to web services, databases, and use of CORS and CORB would be helpful to lock down security risks.