passing props to react component from standard html - javascript

so I wanted to do implement a sort of thing where I can put custom attributes in HTML elements which will be taken as props by a react component. Something like:
function someFunction(props) {
return <h1>props.something</h1>
}
HTML:
<div id="someElement" data-something="some text"></div>
renders:
<h1>some text</h1>
I THINK something like this could work, but I don't think its the best approach
let render_div = document.getElementById("someElement")
render(<someElement something={render_div.getAttribute("data-something")}/>, render_div)
I'm new to react so please help me :)
PS: I'm using typescript

Every data- attribute you set on an HTML element is available inside the element.dataset property. Keep in mind though that there's a naming conversion from dash-style to camelcase (see MDN).
What you should be able to do is something like the following:
<div id="root" data-title="title" data-my-text="my-injected-text" />
import ReactDOM from 'react-dom';
import App from './App';
const rootNode = document.getElementById('root');
const props = element.dataset; // { title: 'title', myText: 'my-injected-text' }
ReactDOM.render(App, props, rootNode);

Related

Component Palette Custom Hook

I am fairly new to React and still wrapping my head around custom-hooks. I cam across a code where a custom hook was created to handle the component imports.
useComponentPalette.js
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
const defaultComponents = {
TodoEditor,
TodoItem,
TodoList,
CheckBox
}
export function useComponentPalette(){
return defaultComponents
}
And then in order to use the hook,
const {TodoItem, TodoList, Checkbox } = useComponentPalette()
My Question :- Does this approach provides any advantage over the regular imports in the component ? or this is an anti-pattern ?
How I usually import the components is as follows
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
function App(){
return(
<>
<TodoList/>
</>
)
}
It's not a good idea to use react hooks like this you can get the same result without react hook
// first file name.js
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
export default {
TodoEditor,
TodoItem,
TodoList,
CheckBox
}
//component file
import * as Component form 'first file name';
//<Component.TodoEditor/>
//or
import {TodoEditor} form 'first file name';
The way that I use react-hooks is for making my code more dry and increase it's readability, so react-hooks is not good fit for this kind of usage.
Hi #Sachin,
In my option, React JS use hook to manage reuse stateful logic between components. In other word, Hooks do well to encapsulating state and share logic. If you want to do some stateful logic or condition base logic with these components, then it's fine with that. But if you are using just without condition in the given components. Then, This Is useless for making the custom hook. You can do that without a custom hook in a simpler way.
Here is a simple way to do that:-
In components folder. I create index file, this is the entry point of all my exporting components
In that file. I export all my components, as you can see.
I use that components like this. It much better way. In my option.
import { Header, Footer, Sider } from "./components"
before using react custom hooks, we should be aware of the rationale behind it.
Customs hooks functionality was provided to reuse stateful logic. If logic doesn't require any state, we will use simple functions and if it is about components only there there are different patterns for making code general and scaleable.
So, there is no usage of custom hook in above case at all. For me, I would go with the following code for above scenario:
// components/index.tsx
import {Todo} from './todo'
import {CheckBox} from './components/CheckBox'
export {
Todo,
CheckBox
}
// componentns/todo/index.tsx
import {Editor} from './Editor'
import {Item} from './Item'
import {List} from './List'
const Todo = {
Editor,
Item,
List
}
export default Todo;
and usage will be like
import { Checkbox, Todo } from "components"
...
<Checkbox ... />
<Todo.List ...>
<Todo.Item ... >
</Todo.Editor ... />
</Todo.Item ... >
</Todo.List>
...
P.S Usage can be different based upon the logic of components, just giving an hint how we can patterns to serve our purpose.
Hope it helps.

How to get access to the underlying component of a react html element?

I'd like to create a <Breadcrumb> component which receives a <Link> component as a dependency.
This could be a <Link> component from react-router-dom or an <a> component.
How can I get direct access to the <a> component so that I may inject it into <Breadcrumb>?
Here is a brief example of what I'm trying to do.
const createBreadcrumbComponent = (Link) => {
return function Breadcrumb(props) {
// return JSX that renders this Link component
// A basic example:
return <Link href="/">{"Home"}</Link>
}
}
An example of using this with react-router-doms own <Link component:
// import {Link} from 'react-router-dom';
const Breadcrumb = createBreadcrumbComponent(Link);
I would like do the same as above, but substitute Link with a. Unfortunately there doesn't seem to be an actual component that represents a (with React.createElement() we pass the string "a" instead).
You can always use ref to access the underlying DOM element from a React Component. But, this is not always the case.
Following are the cases, which will enable you to use ref -
The component is a native HTML element, for eg - a, div, img etc.
The React native component is wrapped with a forwardRef. This doc explains it nicely - https://reactjs.org/docs/forwarding-refs.html
An example for using ref can be seen below -
import React, {useRef} from 'react';
const Comp = () => {
const elRef = useRef();
useEffect(() => {
console.log(elRef.current); // -> the p element
}, []);
return <p ref={elRef}>Hello</p>;
}
There is a third way of getting the underlying element, but I don't recommend it since it is deprecated. You can use ReactDOM.findDOMNode(Component). This is a part of react-dom package.
You can read more about it here - https://reactjs.org/docs/react-dom.html#finddomnode
I think the solution is to create a wrapper around <a>, for instance:
const A = (props) => <a {...props}/>;
const Breadcrumb = createBreadcrumbComponent(A);
I was hoping there would be a way to obtain a component directly from React that already encompasses the <a> element

Is There Any Way to Push React State Into an Import Statement?

So in React, I import a certain file using a statement like so:
import Search from './Pages/search';
However, what if the file I want to import is going to be different every single time I call up a certain function? Would something like this -
import {this.state.fileName} from './Pages/{this.state.extension}';
where the state values are filled in by an outside function, work like I want it to? Say I wanted to download the file that is associated with that dynamic import. Would something like this -
<a href = {this.state.fileName} download> download </a>
allow me to download the file? Is there a better way to go about this? Curious to know.
If the page you want to import is going to change frequently, then may be your component can accept a fileName prop and then you can use that prop to dynamically import that file.
Something like this may be: https://codesandbox.io/s/nervous-bush-xf1zg. Here, the filename changes with each DynamicPage call and the filename that is passed in is imported dynamically within the DynamicPage function.
**Didn't completely understand what you were trying to do but hope this helps
import React, { lazy, Suspense } from "react";
export default function App() {
return (
<div>
<DynamicPage fileName="File1" />
<DynamicPage fileName="File2" />
</div>
);
}
function DynamicPage({ fileName }) {
const DynamicFile = lazy(() => import(`./${fileName}`));
return (
<Suspense fallback={"Loading.."}>
<DynamicFile />
</Suspense>
);
}
import React from "react";
export default function File1() {
return (
<div>
<h1>File 1</h1>
</div>
);
}
import React from "react";
export default function File2() {
return (
<div>
<h1>File 2</h1>
</div>
);
}
It seems like you need to share state between components.
You can:
Pass it as props manually from the parent to each child
or use React ContextApi library
or use some library such as
Recoil
Redux (more complex)

Set required props on component

Say that I create a custom component like this:
const MyComponent = (props) => (
<div
className={props.name}
id={props.id}>
{props.children}
</div>
)
And I need to make sure that props contain the variables name and id, because otherwise what I want to do is not going to work (now I know that this code will work anyhow, but hypothetically say that it won't).
Is there a way in React to demand that certain props are passed to a component?
Maybe this is something that is obvious, but I couldn't find any information about it.
You can use PropTypes. It was earlier a part of React but now it has its own npm package, https://www.npmjs.com/package/prop-types. This will give you a runtime error if ther props are not provided. Its also useful, because linters can warn you if you miss them.
https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = (props) => (
<div
className={props.name}
id={props.id}>
{props.children}
/>
);
MyComponent.propTypes = {
name: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
element: PropTypes.arrayOf(PropTypes.element).isRequired
};

React Components - Where to store HTML Templates

Complete newbie to React and trying to find out how to load the HTML for components rather than inserting it directly in the render method. For example
import React, {Component} from 'react';
export default class Login extends Component {
render() {
return (
<!-- how can I provide a link to the HTML template for here? -->
);
}
}
React does not have HTML. The JSX that you write in the render method is actually compiled into JavaScript. At the core, React components are all JavaScript. The styles are also inline. Componentisation is neat in React because HTML, CSS, JavaScript (interactions) are all in one place, as JavaScript.
To insert raw HTML, React has an attribute dangerouslySetInnerHTML.
<div dangerouslySetInnerHTML={createMarkup()} />
If you want some type of organization, you can use variables to set the html and then assign that to the render functionalty, but React does not use html templates
var hello = React.createClass({
render: yourVariable
});
I think you might be confused about how JSX works.Just in case, I want to clarify that JSX is what they call "syntactic sugar", that turns React methods such as React.createElement into that XML like syntax. For instance:
var Nav;
// Input (JSX):
var app = <Nav color="blue" />;
// Output (JS):
var app = React.createElement(Nav, {color:"blue"});
(from the React docs)
So, to the best of my knowledge, the JSX syntax actually belongs in the render method. If what you are really looking for is the best way to separate and reuse purely presentational code, you should read on separating your app into Container and Presentational components
https://medium.com/#learnreact/container-components-c0e67432e005#.dzjqc8yrn
https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.mn9nf6lz6
Stateless/Presentational/Dumb Components are just functions that return JSX. So you could have your Template component:
import React from 'react';
//you need to import React to use JSX, as it will be expanded into React.createElement calls...
function Template(props){
return (
//...your template here...
);
}
And then your class
import React, {Component} from 'react';
export default class Login extends Component {
render() {
return (<Template {...props}/>);
}
}
}
Makes sense?

Categories