Set a default component for Html Elements in React - javascript

I've been playing with reactjs a bit lately. As I understand, ReactJS will convert html elements into something like this:
<div><span>Text</span></div>
Into
React.createElement('div', null, React.createElement('span', null, 'Text'))
So far so good, but what I'd like to do is have special component that will override all html elements so some kind of basic behavior can be added to any html element using props.
So instead of the above, I'd want something like this instead:
React.createElement(Html('div'), null, React.createElement(Html('span'), null, 'Text'))
This would make it possible to make usual html a bit more dynamic without having to define a new component each time. One alternative in my mind to this would be to have Component based on the props. So adding a particular prop would give a particular trait to the component above.
One example would be to have something like this:
<div foreach="collection" as="value">
<div my-value="value" />
</div>
Just to explain a bit further, the idea is mainly to adapt React to different templating engines. So it's not necessary to rewrite completely templates to work in React and gives some kind of compatibility layer between a legacy templating engine.
So rewriting as this isn't what I'm asking. I already know how to write directly for React.
<div>
{
this.collection.map((value) => {
return <div>{value}</div>
})
}
</div>
One alternative for me which would be quite easy if React can't do that easily is to transform the html elements as Uppercase or differently so React thinks it's a component instead of html.

Related

How to get Vue app container div attribute

I have a page which is being generated by my app in java (SSR) depending on some data (e.g. a publisher for some entity). I would like to create some sort of a reusable Vue component that would call an API method and request some data about the entity that is currently opened. Also in some cases there could be more than one such component on one page.
The only thing I cannot really figure out being a most-of-the-time backend developer - is how to tell a component which entity I'm trying to get. The only solution that comes to my mind is to generate the parent <div class="my-vue-component"><div> with an additional attribute, e.g. <div class="my-vue-component" publisher-id="123"><div>.
But I cannot find if there is a way to access that attribute from inside the Vue instance. (Please note that I don't have a fixed id for this div as there can be many such components on the same page referring to different data).
Any kind of advice is appreciated.
As stated in the previous answer, you will need to use props. Although since you will pass down data to multiple components and the data can change, there should be a way to respond to those changes.
For that, you will have to bind the prop with a reactive variable in your page/parent component.
So your SSR code should look like
<my-vue-component :publisher-id="openId"></blog-post>
And inside your page/parent component will reside the openId, which you can change as needed, and your component will re-render if prop passed to it changes.
export default {
data(){
return {
openId:1
}
}
}
It seems like you are looking for components-props.
You can define a prop like
Vue.component('blog-post', {
// camelCase in JavaScript
props: ['postTitle'],
Your SSR code should then be generating:
<!-- kebab-case in HTML -->
<blog-post post-title="hello!"></blog-post>
Inside the component methods you can access the passed in value using this.postTitle

Best way to include custom react components between strings/p-tags?

tldr: New to frontend. Trying to include custom components within p-tags for a website, I've tried various methods but can't seem to get it to work unless I hard code the content into the return bit in my react component - this isn't viable as I would like to have many p-tags which would change on my website when a user presses next.
Hi everyone! I'm new to front end programming, and this is my very first question, so please excuse any incorrect terminology and/or question formatting!
I'm currently working on a react project where I have created custom components to include in my webpage. These components work when placed between p-tags.
For example, I made a custom component and it works as expected when I do something like:
function test{
return(
<p>Hello! This is a <ShowDefinition word="website"/> which I made using react! </p>
)}
However, I intend to have lots of content which would change using an incremental index, so I've placed my content in a separate jsx file to store as a dictionary.
I found that when doing something like this:
function test{
return(
<div>{script[index].content}</div>
)};
where
script[index].content = '<p>Hello! This is a <ShowDefinition word="website"/> which I made using react! </p>';
it just shows up as a string literal on the webpage. I've tried to wrap my string in {} but this did not seem to work.
I've also tried dangerouslySetInnerHTML with a dompurification to sanitise the html code
dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(script[index].content)}};
This worked however it excluded all of my custom components. So for the example sentence it would show up on the page as "Hello! This is a which I made using react!"
I understand now this doesn't work because dangerouslySetInnerHTML cannot convert custom components/only accepts html, however I am now at a complete lost as to what to do.
I have thought of storing the content in a md file then parsing it however I have little knowledge of md files/md parsers and from what I've found I don't think solves my problem?
Any advice would be greatly appreciated.
Thank you so much.
Ok, so first of all, this is definitely not how you should think when playing with React. Even if this is technically possible with things like React.createElement or dangerouslySetInnerHTML, I suggest you look at this first. I will help you get the thinking in react.
However if I had to do this in React, I would probably use a custom hooks or any conditional logic to render my jsx.
codesandbox
import "./styles.css";
import React from "react";
const useContentFromIndex = (index) => {
return () => {
if (index === 0) return <p> Index 0 </p>;
if (index === 1) return <p> Index 1 </p>;
return <p> Index 2 </p>;
};
};
export default function App({ index = 0 }) {
const CustomContent = useContentFromIndex(index);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<CustomContent />
</div>
);
}

Does VueJs have the concept of Controlled and Uncontrolled Components like React?

React has the concept of controlled and uncontrolled https://reactjs.org/docs/uncontrolled-components.html components.
Where controlled are components working within the react model, and state is tracked in the virtual dom.
And uncontrolled are managed outside the virtual dom.
Since Vue also works with a virtual dom is there a wrong way to grab elements (for instance can you use document.queryBySelector or classList.add like you would if it was vanillajs to manipulate dom)?
It's not wrong to target elements with vanilla JS like you said but it's not the best practice and Vue may reject any outside attempts to mess with the DOM.
When I need to get an specific element from the DOM and manipulate it using vanilla methods I'll always do from within the Vue structure not from a separate file or script. I'd do it like this or some variation of this:
new Vue({
...,
methods:{
setClass() {
let elem1 = document.querySelector("#elem1");
elem1.classList.add("yourClass");
}
},
mounted() {
let elem2 = document.querySelector("#elem2");
}
}
If you want to add of remove classes, I would recommend you to use the Class Binding options native to Vue. And if you're dealing with forms, v-model is the way to go.

What is the use of components in ReactJS instead of a single variable

I started to study ReactJS and can't understand the purpose of components. for instance lets have a component:
var QuoteMaker = React.createClass({
render: function () {
return (
<blockquote>
<p>
The world is full of objects, more or less interesting; I do not wish to add any more.
</p>
<cite>
<a target="_blank"
href="#">
Douglas Huebler
</a>
</cite>
</blockquote>
);}});
why can't we just use
var thisVar = (
<blockquote>
<p>
The world is full of objects, more or less interesting; I do not wish to add any more.
</p>
<cite>
<a target="_blank"
href="#">
Douglas Huebler
</a>
</cite>
</blockquote>
)
instead of that component.
You could. That would be just fine.
What you couldn't do is have a list of those, built from dynamic data.
What if you wanted multiple quotes from multiple people?
What if you wanted a button that randomized which quote appeared?
What if you wanted a twitter feed, or a blog roll, or a comment section?
You don't necessarily need the createClass. That's a particularly old way of looking at things, and you should really be using a Babel build pipeline; full stop.
You can simply say:
const Quote = (props) => (
<blockquote>
<p>{ props.quote }</p>
<cite >{ props.author }</cite>
</blockquote>
);
ReactDOM.render(<Quote quote="..." author="..." />, rootEl);
Now you can happily build a randomizer, or a quote API, or a quote editor, or whatever. The component does what it should, and it leans on input from the outside world for what it shouldn't do.
React allow you to get a composant approach. So you can use as a new balise text (composant) in react. You can reuse this component, it will have the same behavior everywhere.
Functional components
That way that you have in example can be created function, or stateless components, where we can use props object, that can be passed from the parent object.
const Component = (props) => {
//access to props
}
Class component
Class components allows to store thier own state and use it to rerender the component, via this.setState() function:
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
//access to both state and props
}
Why we must use components instead of js objects? Because react has its own DOM - virtual DOM, where it listening to changes and rerendering your real DOM, you can reuse or extend this component anywhere and its also semanticly awesome.
Take a look to the documentation about React components.
There are lots of uses for components. These are few:
Allegedly, if your component has no logics or special use, just flat html, so can pass using component, although it is more encapsulated and looks more neat.
If now or in the future you'll want to use some logics for your component, so it can be handled in the component. That is the Object Oriented approach for using html block of code. If your'e coming from Angular, you can think of it as "directive", from .Net "User control". Well, not exactly, but the purpose is same.
Calls and uses to different libraries. It is a better practice not to require libraries as global variable, but only for your use in the component.
And of course the most important factor: You can take advantage of the react "digest loop". You can choose what to do on constructing, before rendering, after rendering, and much more.
You can look it up here: https://facebook.github.io/react/docs/react-component.html
As i said before, there are lots of uses for components over flat html, and basically this is the whole point of ReactJS as component based :)

Handling event using custom data attributes or binding data to the handler?

I'm using React, but this is not necessarily a React specific question.
Is there a major difference between grabbing a custom data attribute in an event handler
<MyElement greeting="hello" farewell="goodbye" />
//MyElement component
handleClick(event) {
console.log(event.currentTarget.dataset.myData);
}
...
<li data-my-data={this.props.greeting} onClick={this.handleClick}>Click Greeting</li>
<li data-my-data={this.props.farewell} onClick={this.handleClick}>Click Farewell</li>
and binding a value to the event handler
<MyElement greeting="hello" farewell="goodbye" />
//MyElement component
handleClick(myData) {
console.log(myData);
}
...
<li onClick={this.handleClick.bind(this, this.props.greeting)}>Click Greeting</li>
<li onClick={this.handleClick.bind(this, this.props.farewell)}>Click Farewell</li>
Is this just a matter of personal preference or are there actual pros and cons to each of these?
Short answer: it is a matter of personal preference AND there are Pro's and Con's to each solution.
IMHO Option 1 is a shortcut around react design principles, which can get you in a lot of trouble later on.
PRO Option 1: 'store' the data in DOM dataset:
Less tedious binding stuff in your component
dataset is also accessible from outside the react component; other components / code can directly read/ update dataset
PRO Option 2: 'store' the data in react javascript component
Less worries if the target passed is the right DOM node. (event.currentTarget takes first higher up component with event listener, event.target takes clicked element)
dataset is only accessible from inside react component, keeping your code cleaner
My personal preference is option 2: It forces you to stick to react dataflow and design principles, and keeps all relevant code in the same place, inside the javascript react component.
This safeguards you from the following route to hell (especially prevalent in larger projects and larger teams):
new requirement: some remote component needs access to dataset
the proper redesign of react component tree is tedious: you may need to move management of dataset to a higher component to give access to dataset, which means revision of react component tree.
but a shortcut is available: the remote component can also read directly from DOM - so go for the quick and dirty solution
new requirement: the original component needs an update
now there is no way of finding out which other components actually read/ rely on the dataset, so your code has in effect become unmanageable.
Do it like this, using ES6 arrow function:
<li onClick={()=>this.handleClick(this.props.greeting)}>Click Greeting</li>
This is cleaner and more efficient than bind, and requires much less code than option (1).
Only (potential) disadvantage is that in this case you create new function object every time during render(). Which will only be the problem when you're passing the callback to the custom component which is relying on shouldComponentUpdate() optimization. In this case, option (1) should work the best, as you should avoid dynamically created closures.

Categories

Resources