In the documentation of styled-components you commonly see the following notation used in examples
const Button = styled.button`
color: palevioletred
`;
render(
<Button>Click me</Button>
);
JSX being passed as a parameter to render really threw me off when I was starting to learn styled-components. Is this some kind of alternative notation in React, that I somehow missed? Is it meant as pseudo code shorthand for the return value of React's render function? Is it some kind of DSL that can be used with styled-components?
The styled-components web page uses React Live to render demo components, so that render() is a specific imperative form enabled by React Live and is not directly related with styled-components.
That being said, there's nothing special in passing JSX to a render() function: you usually do that with ReactDOM.render(). JSX compiles into React.createElement(), so what you're actually passing to the function is a React element.
Related
I'm confused on the point of React.forwardRef. As explained in its documentation, I understand that its main use is for a Parent Component to gain access to DOM elements of the Child Component. But I can already do that without even having to use it.
Here is a code example that you can plug into CodeSandbox and see that it works:
import React, {useRef, useEffect} from "react";
import "./styles.css";
const ChildComponent = (props) => {
useEffect( ()=> {
props.callbackFunction()
})
return(
<div ref={props.fRef}>
{"hello"}
</div>
)
}
export default function App() {
const callbackFunction = () => {
console.log("The parent is now holding the forwarded ref to the child div: ")
console.log(forwardedRef)
}
const forwardedRef = useRef(null)
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<ChildComponent name="gravy" callbackFunction={callbackFunction} fRef={forwardedRef}/>
</div>
);
}
Or here's the embed of this example. Honestly, I'm kind of new to this and I don't know exactly how embeds work and whether someone fiddling with the embed changes my original Sandbox or not, so I was hesitant to put it. But here it is.
Example Forwarding Ref
In the example, the parent App() component successfully passes a ref to the child which the child attaches to its rendered div. After it renders, it calls a callback function to the parent. The parent then does a console log where it proves that its forwarded ref now has a hold of the child's div. And this is all done without React.forwardRef.
So what then is the use for React.forwardRef?
You're absolutely right that you can do what you've described. The downside is that you're forced to expose an API (ie: the fRef prop) for it to work. Not a huge deal if you're a solo developer building an app, but it can be more problematic eg. if you're maintaining an open-source library with a public API.
In that case, consumers of the library won't have access to the internals of a component, meaning you'd have to expose it for them somehow. You could simply do what you're suggesting in your example and add a named prop. In fact, that's what libraries did before React 16.3. Not a huge deal, but you'd have to document it so people know how to use it. Ideally, you'd also want some kind of standard that everyone used so it wasn't confusing (many libraries used the innerRef naming convention), but there'd have to be some consensus around that. So all doable, but perhaps not the ideal solution.
Using forwardRef, passing a ref to a component just works as expected. The ref prop is already standardized in React, so you don't need to go look at docs to figure out how to pass the ref down or how it works. However, the approach you describe is totally fine and if it meets your needs, by all means go with that.
As mentioned in the docs , it's useful for highly reusable components, meaning components that tend to be used like regular HTML DOM elements.
This is useful for component libraries where you have lots of "leaf" components. You've probably used one like Material UI.
Example:
Let's say you're maintaining a component library.
You create a <Button/> and <Input/> component that maybe just adds some default styling.
Notice how these components literally are just like regular HTML DOM elements with extra steps.
If these components were made to be used like regular HTML DOM elements, then I expect all the props to be the same, including ref, no?
Wouldn't it be tedious if to get the button ref from your <Button/> component I'd have to get it through something like fRef or buttonRef ?
Same with your <Input/>, do I have to go to the documentation just to find out what ref to use and it's something like inputRef ? Now I have to memorize?
Getting the ref should be as simple as <Button ref={}/>
Problem
As you might know, ref will not get passed through props because, like key, it is handled differently by React.
Solution
React.forwardRef() solves this so I can use <Button ref={}/> or <Input ref={}/>.
I'm fairly new to React and started checking out React-Bootstrap and the way the components are styled. The documentation clearly styles components with variant:
<Button variant="primary">Success</Button>
However, this code seems to work just as well with the traditional className. Functionally, and aesthetically, if I change the above code to something like,
<Button className="bg-primary">Success</Button>
the output is the exact same. Personally, I find using the className attribute much easier as I can write vanilla bootstrap classes like btn btn-primary... instead of different react-bootstrap classes.
Is there any functional difference between the two and is there a reason to use variant over className?
The difference between variant and className:
Variant:
- uses only pre-defined classes
- no need for an external library
className:
- can use custom classes
- works the same as the HTML attribute class
I personally use className
I personally don't use React-Bootstrap, preferring to include the CDN to Bootstrap and apply classes to my own components using className.
As far as I can tell, there is no functional difference between both methods.
Variant is a prop for your React-Bootstrap components which wrap the various predefined styles for the different bootstrap components. You can't customise a React Bootstrap component using a variant(if you want to deviate from bootstrap's theme).
ClassNames are your normal CSS classes wherein you can add any style to components through CSS. The reason className="bg-primary" would work because React-Bootstrap has the bootstrap's css file included as part of the library.
this is the bootstrap Button Component:
const Button = props =>{
const variant = props.variant?`btn-${props.variant}`:""
return(
<button className={`btn ${variant} ${props.className}`}
onClick ={props.onClick}>
</button>
)
}
Suppose I cannot change this statement in my sourcecode:
<div dangerouslySetInnerHTML={{ __html: template }} />
How can I replace the template for a react component? Like:
<div dangerouslySetInnerHTML={{ __html: someReactComponent }} />
How can in insert a reactjs component in ?
As commented by FrankerZ,
Why do you even have to do this? <div><someReactComponent /></div>. There's a reason why it uses the word "dangerously"...avoid using it if you have to.
Yes, obviously. You shouldn't be using dangerouslySetInnerHTML most of the time as far as possible.
If you are trying to render static markup, then you may use renderToStaticMarkup. The linked post has also stated that but will not work because it is being used from React instance. You need to use it from ReactDOMServer:
import ReactDOMServer from 'react-dom/server';
ReactDOMServer.renderToStaticMarkup(statticElement)
This doesn’t create extra DOM attributes that React uses internally, such as data-reactroot. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save some bytes.
See the docs for more information on it.
I am currently getting to grips with the react-spring animation library.
In some of the CodeSandbox demos (e.g. https://codesandbox.io/embed/j150ykxrv) in the documentation, something is imported called "animated":
import { Transition, animated } from 'react-spring'
and then used like so:
{this.state.items.map(item => styles => <animated.li style={{ ...defaultStyles, ...styles }}>{item}</animated.li>)}
In other examples this isn't used:
import { Spring } from 'react-spring'
<Spring
from={{ opacity: 0 }}
to={{ opacity: 1 }}>
{props => <div style={props}>✌️</div>}
</Spring>
I can't find any mention in the documentation of what this does or why it is used, as it seems you can animate by just passing animated style props into a component.
Are the uses in the documentation part of a legacy version?
Native is optional, if you set it (and then you need the component to extend from animated.xxx) it won't render out the animation like normally react animation libs would do, in other words they call forceUpdate or setState on every frame, which is expensive. With native it will render the component once, then animate in the background using a requestAnimationFrame-loop which sets the styles directly. The values you pass to your target div (or whatever) are not numeric values but classes that receive update events, this is why you need to extend.
Rendering through react is not obsolete, though, it is the only way you can animate React component props. If you have a foreign control, or a D3 graph for instance, you would simply blow props into it while the spring renders them out.
Looking further into the docs, I can see it is used for "native" rendering.
This allows react-spring to bypass React for frame updates. The benefits of this method are improved performance.
It is recommended to use this approach
"Try doing this in all situations where you can"
Just be aware of the following conditions:
native only animates styles, attributes and children (as textContent)
The values you receive are opaque objects, not regular values
Receiving elements must be animated.[elementName], for instance div becomes animated.div
If you use styled-components or custom componemts do: animated(component)
If you need to interpolate styles use interpolate
Summarised benefits:
Your application will be faster, the difference really can be night
and day
You get quite powerful interpolation and keyframing tools (see
below)
You get to animate scrollTop and scrollLeft out of the box (which
React can't normally handle)
Looks like it is used for doing native rendering,take a look a the Transition component , it has a native prop
In React JS documentation,
it is mentioned Elements are the smallest building blocks of ReactJS.
But, Components are also built, in order to create Elements.
For example,
const element = <Welcome name="Sara" title="Mara"/>;
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
So, Component (here Welcome function component) was smallest building block that helped create an Element.
So, Does it mean Components are the smallest building blocks? It is confusing. Please clarify.
A react component is made up of simple html elements. But a react component's smallest element is the react component itself.
A react component is actually an object with fields {type:..., state:..., props:...., children:....,} Where children will be componsed of other subtree objects(react elements). This object is used for calculating the difference in dom when a component is rerendered(on change of state or props) and pushing the objects with change and ignoring those which doesnt change.
React is all about components. When you have complex DOM ( DOM is made up of elements ) it's React's way to break that complex DOM into granular smaller components.
The more granular it is, you are doing it the more React way (It's a React best practice).
coming to "Components are the smallest build blocks ?", well we can't say it that way, we can say "React is all about components"
It depends on us that how well we create granular components, which makes it easily reusable and maintainable.
Creating granular components always doesn't mean creating components with just one element.
Granular Component ?
import React from 'react';
const welcome = (props) => (
<div>
<p>props.welcomeMessage</p>
<h3>Disclaimer</h3>
<p>props.disclaimerMessage</p>
</div>
);
export default welcome;
I can call this a granular component but we can also debate on the Disclaimer part of this code, Disclaimer also can be used elsewhere so it's always a good practice to identify such pieces and move them into there own components so that we get the complete benefits of React
We cannot call a component the smallest building block but yes we can break the HTML into proper, well-structured Component Tree to get the smallest ones.
Elements and Components are different things in React, and the documentation you read explains the first of those, the element.
Elements:
Elements are plain JavaScript objects that describe how your UI should be rendered.
If you are using JSX, describing elements looks quite similar to writing HTML.
// The `<div />` is JSX for creating a React *Element*
const element = <div>Foo</div>;
Components:
Components are separate from elements. As mentioned in the Components and Props doc, components are "like JavaScript functions" and "return React elements describing what should appear on the screen."
React Components return React Elements describing what should appear on the screen
// This is a React *Component*: a Function that returns a React *Element*.
function MyComponent() {
return <div>Foo</div>;
}
// You can also implement a React *Component* by extending `React.Component`
// and implementing a `render` method.
class YourComponent extends React.Component {
render() {
return <div>Foo</div>;
}
}