I'm self-teaching React and was just wondering if someone could clear something up for me.
I have this component, which seems to be doing everything I need it to:
const Projects = ({ projectData }) => {
const { url } = useRouteMatch();
return (
{projectData.map((project) => (
<div className="project-container" key={project.id}>
<div className="project-image">
</div>
<div>
<h2>{project.name}</h2>
<p>{project.description}</p>
<div>
<Button class="button link_right relative" linkTo={`${url}/${project.id}`} btnText="Explore" />
</div>
</div>
</div>
))}
);
};
export default Projects;
While watching tutorials and reading documentation I'll typically see Function and Class Components but not whatever this is:
const ComponentName = () => {
So, my questions are:
What sort of component is my example known as
What purpose does it
serve when compared to a Function Component or a Class Component,
How would a Function Component or a Class Component need to look in
order to do everything that my example component is currently doing.
Thanks!
Making instance of class is too slow, because of calling constructor and inheritance. Functional components are just functions, there are no such overheads.
In addition, there is how to treat this. In class, entity of this is often unclear and that confused us. Arrow function reduce it, but using class, we must use this. this caused complicated management of state too. And class object has state itself, so it was troublesome.
Function, defined carefully, is easy to keep purity. It has no state itself. It means that state management is not bother us. Data flow is cleared.
Related
I am trying to follow the persistent layout examples as presented on the official docs and Adam Wathan's article here.
This is what I know so far:
I am aware about React's reconciliation process. I know that if react realizes the virtual dom tree of a component hasn't changed, then it wont update the html dom elements of that tree/component. Article I used to better understand some of these concepts
React rerenders a component if its state changes. If a prop changes, it should not? Or is there an assumption that a prop is implicitly considered a state?
If a parent re-renders, then children will be re-rendered.
I am aware (though still need to learn/readup) on React.memo. Once I do, I plan to utilize that as well. I am vaguely aware that it caches the component for the given input (props) and if props doesn't change, it returns the cached component.
Based on the above, I would say that persistent layout works because the layout used in _app.js is provided the page as its prop (children). Since layout's own state doesn't change, layout shouldn't get re-rendered. However, that is not what I am noticing, and hence this long winded question.
Just so I am clear, when i say re-render, I am talking about React recreating the virtual dom for the component rather than repainting the html dom. My issues are with the former and not the later.
What I am seeing is that every time I click on the "Profile" link (even if I am already on the same page):
The entire layout (including top nav bar, icons, search bar and links) all re-render.
I see the console log messages being printed for each of them.
I used the "Profiler" tool and it too shows me all the components rerendering.
I thought that a persistent layout meant that it wouldn't be re-evaluated all the time? The printing of console logs indicates that the component is being re-evaluated every time. I know React.memo would avoid this entirely, but then what exactly is "persistence" about this? What am i missing or failing to understand about persistent layouts in this case?
What I have looks like this:
/pages/profile.js (and similarly /pages/anotherPage.js)
function sampleProfilePage (props) = {
return (
<div>I am on profile page</div>
);
}
export default sampleProfilePage
_app.js
function MyApp({Component, pageProps}) {
return (
<SimpleLayout>
<Component {...pageProps} />
<SimpleLayout />
);
}
SimpleLayout.js
function SimpleLayout ({children}) {
return (
<>
{console.log("simpleLayout re-rendered")}
<SimpleTopBar />
<main>{children}</main>
</>
);
}
export default SimpleLayout;
SimpleTopbar.js NOTE: css can be ignored. Its present in .module.css file.
function SimpleTopBar () {
return (
<div className={classes.container}>
{console.log("SimpleTopBar re-rendered")}
<Link href="/profile">Profile</Link>
<IconCircle />
<SearchBar />
<IconSquare />
<Link href="/anotherPage">Another Page</Link>
</div>
);
}
export default SimpleTopBar;
IconCircle (and similarly IconSquare) NOTE: ignore css again. Also, I recently became aware that defaultProps are deprecated. I am in the process of updating/writing inline default values.
export function IconCircle (props) {
return (
<svg xmlns="http://www.w3.org/2000/svg"
className={props.name}
... rest of svg data ...
</svg>
);
}
IconCircle.defaultProps = {
name: classes.iconCircle
}
SearchBar.js NOTE: this is taken straight from Adam's code in order to try and compare what I was seeing.
function SearchBar (props) {
return (
<div className="mt-2">
{console.log("Search bar rendered")}
<input className="block w-full border border-gray-300 rounded-lg bg-gray-100 px-3 py-2 leading-tight focus:outline-none focus:border-gray-600 focus:bg-white"
placeholder="Search..."
/>
</div>
);
}
export default SearchBar;
Disclaimers:
I am a backend engineer and just starting to learn React and Nextjs. Its is highly possible that my design and understanding is limited or not exactly what one might expect in the industry/professionally. So, if there are some general practices or commonly known knowledge, please do not assume that I am following that or aware of it. Its part of the reason why I pasted entire functions. I am still reading up on various pages/questions and trying various things to rule things out, or understand better what is being shown/told to me.
Thank you in advance for the patience to read this question, and sorry for its length.
You have a pretty good understanding of what's happening.
All pages in Next.js depend on _app - it rerenders because of pageProps or more likely Component prop changes - forcing the children to rerender.
The layouts will 'persist' between pages - the children should rerender on a route change but, components that are still on the page should keep their state.
i.e. a search input in the layout should keep its search term on route changes to another page with the same layout.
The only way not to rerender during route change is to use shallow routing . But it doesn't really route - it just allows you to add query params to the current route (can't change pages or it will use standard routing).
As you mentioned, you can use memo on some of your components to prevent rerendering, but only use it when you know you need it and use it wisley.
Lastly, rerendering is also part of React and virtual DOM manipulation, I wouldn't worry about it too much until it becomes a problem.
class SearchInput extends React.Component {
constructor(props) {
super(props);
this.searchInputRef = React.createRef(); // 👈️ LOOK HERE
}
onFormSubmit = (e) => {
e.preventDefault();
// const query = e.target.querySelector("#searchInput").value; // 👈️ LOOK HERE
const query = this.searchInputRef.current.value;
console.log(query);
};
render() {
return (
<form onSubmit={this.onFormSubmit}>
<div className="input-group-text">
{this.props.label}
<input
type="text"
className="form-control"
id="searchInput"
aria-describedby="emailHelp"
placeholder="Search"
ref={this.searchInputRef}
/>
<button type="submit" className="btn btn-primary">
<i className="fas fa-search"></i>
</button>
</div>
</form>
);
}
}
I'm very new to ReactJS, but I'm having hard times with it, I have two questions about my component above:
on the first // 👈️ LOOK HERE comment above, you see, I'm saving the references to the class instance itself (in the constructor) which leads to two downsides:
The constructor will become very messy later when I add 7 or 8 references inside of it, which makes it non-clean code.
We're saving the reference to the object body of the class instance, do you think this is a clean-code? maybe there should be something in React that allows me to store all the references inside one property may be called "refs", so the instance of that class would look like the following:
{
refs: {
searchInputRef: ...
// later
buttonRef: ...
button2Ref: ...
iconRef: ...
}
state: ...
// the rest of the component object
}
Which is more cleaner if you ask me.
If I'm wrong, please let me know.
on the second comment // 👈️ LOOK HERE of course you can see I don't actually need a reference in my case, so why I'm using ref sys~? I can simply get the input from e.target.querySelector("#searchInput") as simple as it looks like, why folks are always saying it's a shame and a bad practice to use my beloved querySelector to reference DOM elements when using React?
Well, I think the people you mentioned (those who say using DOM is embarrassing) are completely wrong!
They have probably never read the official ReactJs documents and are merely expressing their personal (and completely wrong) opinion.
Stop Overuse Refs!
According to the documentation on the ReactJs website, overuse of the Refs is completely wrong. ReactJs recommends that you do not even use open() or close() modals.
So the best option we can choose is to use DOM.
But this does not mean that ReactJs has put a useless thing in its library facilities. Not at all.
So when to Use Refs?
There are some great cases where using Refs is very economical. For example, to focus on fields or create multiple animations.
In my opinion, there is nothing that Refs can not do. And on the other hand, there is nothing that can not be done with DOM. Both are fully functional.
What matters is the performance and efficiency of each.
DOM is a proven thing in the web world, but according to ReactJs, overuse of Refs can be harmful.
Anyway, this is a general overview of Refs and DOM that I would like to share with you.
I hope other people give you suggestions on how to use Refs better.
Finally, there is another important issue.
I understand from your question that you care a lot about the performance of your program. But I was wondering why you do not use functional components instead of class components?
Using functional components can greatly enhance the performance, efficiency and speed of your program. I hope you read about it and improve the performance of your program by migrating to functionals.
Please Read This Articles:
Components and Props
Introducing Hooks
React Function Components
At first // 👈️ LOOK HERE,
You could have a function to create ref, to distinct them i prefer an id.
class SearchInput extends React.Component {
constructor(props) {
super(props);
}
refs = {} // 👈️ LOOK HERE
getRef(id) { // 👈️ LOOK HERE
if (!this.refs.hasOwnProperty(id)) {
this.refs[id] = React.createRef();
}
return this.refs[id];
}
render() {
const
return (
<form onSubmit={this.onFormSubmit}>
<div className="input-group-text">
{this.props.label}
<input
type="text"
className="form-control"
id="searchInput"
aria-describedby="emailHelp"
placeholder="Search"
ref={this.getRef(id)} // 👈️ LOOK HERE, id - you decide
/>
<button type="submit" className="btn btn-primary">
<i className="fas fa-search"></i>
</button>
</div>
</form>
);
}
}
At second // 👈️ LOOK HERE, i think this question has been asked you should do a search for it.
i'm rebuilding my portfolio with ReactJS as i'm learning this new language and i have 1 question. Should i use state or props only in a website where no content will need to be updated?
This is my main class:
class App extends Component {
state = {
name: 'My name',
job: 'Desenvolvedor Web'
}
render() {
return (
<div className="App">
<Header name={this.state.name} job={this.state.job}/>
</div>
);
}
}
And this is my Header.js
const Header = (props) => {
return(
<div className="Header">
<div className="conteudo text-center">
<img src="" className="rounded img-circle"/>
<h1>{props.name}</h1>
<h2>{props.job}</h2>
</div>
)
}
I guess my entire one page portfolio will follow this structure path, with not a big use of handles and changes in my DOM.
I'm sorry for this noob question, i'm really trying my best to learn React.
You should use both state and props in conjunction with one another. You're using both in your code perfectly fine. State is something that is managed by a component and can be passed down to a child via the props. A simple way of understanding this is that you can pass down the Parent component's state (App) to the child (Header) in the form of props which is an important concept in React.
State is both readable and writable whereas props are read only. Also, any change in the components state triggers a re-render.
Here, your state acts as the top/root level for the data that can be passed down to other components if it needs to be used again.
See these for more info.
What is the difference between state and props in React?
https://flaviocopes.com/react-state-vs-props/
State is for properties of your component that change and in turn cause your component to re-render. If you are only passing data down to read, props are a more appropriate choice.
Well I don't know if I am allow to post a question like this which is obviously more generic. But I just wanted to clarify and understand more about React reusable components. I have a component which holds information to open modals, and to insert user input.
I wanted to create the same component - when it comes to the design - but instead of having inputs and modals I just wanted to display information.
Is it possible for me to use the same visual component with different purposes such as to Input data and Visualize data? How would I do that since the input and the modal component uses logic and its internal state to open modals and uses methods from its parent to handleInputData? how do I switch these functionalities?
Yes, of course. It's the core feature of React, the declarative composition of components.
For instance, let's say that you have a Modal component which handles the display of something on the screen, above other content. You can use the props to customize what it renders right?
Them, you will specialize that component with your different behaviours, like a form or displaying information.
Example (conceptually):
const Modal = ({ title, children }) => (
<div className="modal">
<h1>{ title }</h1>
<div className="body">
{ children }
</div>
</div>
)
const FormModal = () => (
<Modal title="What's your name?">
<form>
{ /* your form here */ }
</form>
</Modal>
)
const AlertModal = () => (
<Modal title="Something happened">
{ /* your information to display here */ }
</Modal>
)
I am still a noob at React and in many examples on the internet, I see this variation in rendering child elements which I find confusing. Normally I see this:
class Users extends React.Component {
render() {
return (
<div>
<h2>Users</h2>
{this.props.children}
</div>
)
}
}
But then I see an example like this:
<ReactCSSTransitionGroup
component="div"
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>
{React.cloneElement(this.props.children, {
key: this.props.location.pathname
})}
</ReactCSSTransitionGroup>
Now I understand the api but the docs don't exactly make clear when I should be using it.
So what does one do which the other can't? Could someone explain this to me with better examples?
props.children isn't the actual children; It is the descriptor of the children. So you don't have actually anything to change; you can't change any props, or edit any functionality; you can only read from it. If you need to make any modifications you have to create new elements using React.CloneElement.
https://egghead.io/lessons/react-use-react-cloneelement-to-extend-functionality-of-children-components
An example:
main render function of a component such as App.js:
render() {
return(
<Paragraph>
<Sentence>First</Sentence>
<Sentence>Second</Sentence>
<Sentence>Third</Sentence>
</Paragraph>
)
}
now let's say you need to add an onClick to each child of Paragraph; so in your Paragraph.js you can do:
render() {
return (
<div>
{React.Children.map(this.props.children, child => {
return React.cloneElement(child, {
onClick: this.props.onClick })
})}
</div>
)
}
then simply you can do this:
render() {
return(
<Paragraph onClick={this.onClick}>
<Sentence>First</Sentence>
<Sentence>Second</Sentence>
<Sentence>Third</Sentence>
</Paragraph>
)
}
Note: the React.Children.map function will only see the top level elements, it does not see any of the things that those elements render; meaning that you are providing the direct props to children (here the <Sentence /> elements). If you need the props to be passed down further, let's say you will have a <div></div> inside one of the <Sentence /> elements that wants to use the onClick prop then in that case you can use the Context API to do it. Make the Paragraph the provider and the Sentence elements as consumer.
Edit:
Look at Vennesa's answer instead, which is a better explanation.
Original:
First of all, the React.cloneElement example only works if your child is a single React element.
For almost everything {this.props.children} is the one you want.
Cloning is useful in some more advanced scenarios, where a parent sends in an element and the child component needs to change some props on that element or add things like ref for accessing the actual DOM element.
In the example above, the parent which gives the child does not know about the key requirement for the component, therefore it creates a copy of the element it is given and adds a key based on some unique identifier in the object. For more info on what key does: https://facebook.github.io/react/docs/multiple-components.html
In fact, React.cloneElement is not strictly associated with this.props.children.
It's useful whenever you need to clone react elements(PropTypes.element) to add/override props, without wanting the parent to have knowledge about those component internals(e.g, attaching event handlers or assigning key/ref attributes).
Also react elements are immutable.
React.cloneElement( element, [props], [...children] ) is almost equivalent to:
<element.type {...element.props} {...props}>{children}</element.type>
However, the children prop in React is especially used for containment (aka composition), pairing with React.Children API and React.cloneElement, component that uses props.children can handle more logic(e.g., state transitions, events, DOM measurements etc) internally while yielding the rendering part to wherever it's used, React Router <switch/> or compound component <select/> are some great examples.
One last thing that worth mentioning is that react elements are not restricted to props.children.
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts />
}
right={
<Chat />
} />
);
}
They can be whatever props that makes sense, the key was to define a good contract for the component, so that the consumers of it can be decoupled from the underlying implementation details, regardless whether it's using React.Children, React.cloneElement, or even React.createContext.