REACT : all method in class are run 2 time - javascript

Firstly sorry if my English is not perfect, i learn :x
I have a problem withe react, all my components is run two time, for example if i write "console.log('test');" in the render function, so i see "test" two time in the console...
just for specify, i don't have this problem when i use a function for a component and in class all default methods (constructor, render, componentDidMount, ... ) is run two time when the components is create or modify (not destruct the componentWillUnmount is been run one time).
the problem is not from my code, i tried to create a new app (with create-react-app) and change function by a class but the result it's the same (even on a other computer)
the only file i have change after create the project (i have change only line 1, line 5 and line 7):
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
console.log('test');
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
export default App;
I specify too, i have already read that react prefer function now, class is depreciated, but i learn currently react and i like explore all possibility :)
Thanks for your help ;) and sorry again for my English :x
Edite :
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
constructor() {
super()
console.log("test")
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
export default App;
In this case console.log() is run two time too, but the constructor is not run when we do an update so it's not that the problem

First of all, you should understand the usage of React lifecycle methods such as render(), componentDidMount().
The render() method is called whenever state changes, when you run setState() method render() method will be triggered again. So render() is the method which is customizing your UI continually according to the application state. You can't control the method to run only once since you need to re-generate the UI frequently. You have to refer to the stateful and stateless components in React.
Stateless components will be generated once and cannot change the state unless you re-create the component.
Source
The reason for the stateful component render() method is triggered two times. You have to understand React Virtual DOM which React initially renders the changes in virtual DOM and identify the specific changes effected then it renders only the changed UI in a real DOM.
Updating the browser’s DOM is a three-step process in React.
Whenever anything may have changed, the entire UI will be re-rendered in a Virtual DOM representation.
The difference between the previous Virtual DOM representation and the new one will be calculated.
The real DOM will be updated with what has actually changed. This is very much like applying a patch.
Literally the render method will be called in virtual DOM and real DOM in stateful components. Write only the UI logics in the render() method do not write functional logics such as sending HTTP requests, you can write those into componentDidMount() method.
Refer the explanation Stateful vs Stateless

Related

How can I fix the error on my React App after trying to export a functional component?

My biggest problem is that I have not been able to get my react app to display since the first week of the course's assignment. I am at the end of the second week, and have been dealing with this second assignment for several weeks since the course is online through coursera.org.
I have gone over the assignment from week one and watched the videos over and over again, and made many revisions after googling a lot of the answers to the correct code. I have also gone through the resources of week one that the course offers.
I posted numerous times on week one's discussion board and follow the suggestions given. I still was not able to get the react app to display, so I moved one the week 2 assignment, and continued working on it.
After more than two weeks of a lot of trial and error and following the error prompts from the visual studio which is the one I am using for this course, I finally started to get some input on what errors I needed to fix on the editor through the cmd window. Every time I make corrections and run yarn start again, the app started to let me know what I needed to fix on the code. The following image is the last error that I got. Any suggestions are greatly appreciated.
This is the code of the functional component that is giving me the error.
import React from 'react';
import { Card, CardImg, CardImgOverlay, CardTitle, Breadcrumb, BreadcrumbItem } from 'reactstrap';
import {Link } from 'react-router-dom';
import { DishDetail } from 'reactstrap';
import { Menu } from 'reactstrap';
function RenderMenuItem ({dish, onClick}) {
return(
<card>
<Link to={`/menu/${dish.id}`} >
<cardImg width = "100%" src ={dish.image} alt={dish.name} />
<cardImgOverlay>
<cardTitle>
{dish.name}
</cardTitle>
</cardImgOverlay>
</Link>
</card>
);
}
function Millie (props) {
const menu = props.dishes.map((dish)=>{
return(
<div key={dish.id} className="col-12 col-md-5 m-1">
<RenderMenuItem dish={dish} />
</div>
);
});
}
return(
<div className="container">
<div className="row">
<Breadcrumb>
<BreadcrumbItem><Link to="/home">Home</Link></BreadcrumbItem>
<BreadcrumbItem active>Menu</BreadcrumbItem>
</Breadcrumb>
<div className="col-12">
<h3>Menu</h3>
<hr />
</div>
</div>
<div className="row">
{menu}
</div>
</div>
);
export default function Menu(){
}
Almost all if code has been provided by professor.
Error page from React App
Any suggestions are greatly appreciated!
ty
Mildred
As the error says, you're trying to declare something called "Menu" when something called "Menu" already exists.
import { Menu } from 'reactstrap';
export default function Menu(){
}
Either rename the Menu function component or rename the imported one:
// either rename this on import
import { Menu as ReactStrapMenu } from 'reactstrap';
// or call your Menu component something else
export default function MyMenu () {
}
As Chris points out in the comment below, it seems likely that you don't intend to export the empty Menu function at the bottom at all, and perhaps meant to export your Millie component? In that case, just replace the default export at the end with:
export default Millie;
Or export it in the same place you're defining it:
export default function Millie (props) {
const menu = props.dishes.map((dish)=>{
// etc.
}
Mildred! Nice that you're practicing, courses are awesome to learn the basics.
As described in the error you provided, "Menu" is declared twice. If you check the code snippet, you can see that you imported "Menu" from a library, but also declared a function called "Menu".
That is where that error comes from. Just change your default function to any other name, such as "MyMenu"

How to create a conditional rendering of Gatsby's Link component and <a> tag for links?

From Gatsby's official docs regarding Gatsby's Link component, it states that the Link component is used only for internal links, whereas for external links, one has to use the tag.
I'm building a Button component that has inbuilt props for links. The problem is right now I have to create 2 separate Button components for internal and external links due to the limitation.
My goal is to use one freeLink component that can be used as both internal and external links
I've tried creating a subcomponent (Button) for the button, but I'm unsure of the parent component (freeLink) which requires conditional rendering. The subcomponent is as of follows:
const Button = props => (
<button className={props.btnType}>
<span>{props.text}</span>
</button>
)
This is the visual logic to what I want to achieve:
For Internal links
<freeLink intLink="/about" btnType="btn-cta" text="Read about us">
</freeLink>
...which will render...
<Link to="/about">
<button className="btn-cta">
<span>Read about us</span>
</button>
</Link>
It is relatively similar for external links
<freeLink extLink="https://google.com" btnType="btn-cta" text="Visit Our Partner">
</freeLink>
...which will render...
<a href="https://google.com">
<button className="btn-cta">
<span>Visit Our Partner</span>
</button>
</a>
I'm quite new to Javascript, Gatsby and React so I'm unsure to how to apply a conditional rendering based on props applied.
Any advice, suggestion, or direction to how to code up the freeLink component is greatly appreciated.
P.S: I've seen Conditionally Use Gatsby Link in React Compoment but the chosen answer is too complicated for me to understand, and I don't have enough points to comment to ask for further elaboration.
You could try something simple like this:
const MyLink = (href, text, ...props) => {
if (href.startsWith("http") {
return <a href={href} {...props}>{text}</a>
} else {
return <Link href={href} {...props}>{text}</Link>
}
}
Your component could return different stuff based on weather you pass it a to or a href prop:
import { Link } from "gatsby"
const freeLink = props => {
if (props.to) return <Link {...props} />
return <a {...props} />
}`

Simple button component not accepting variables

In reviewing and making my code more modular and robust, as any programmer should, I noticed I was using a similar button component multiple times. As such I decided to create a button component and just render it with the new route link and text as in the page rendered.
I'm completely new to react (~ 5 days in learning) with a fairly well versed programming background.
Simple component button, I use react-route-dom : Link prop to route to new pages.
function ActionButton () {
return (
<div className="Action">
<button className="ActionButton">
<Link to={this.props.navLink}>
{this.props.text}
</Link>
</button>
</div>
);
}
using/constructing of the button component
function ActionPage () {
return (
<div className="ActionPage">
<ActionButton
navLink="/urlLink1"
text="btn1"
/>
<ActionButton
navLink="/urlLink2"
text="btn2"
/>
</div>
);
}
this doesn't work, I get the following:
TypeError: Cannot read property 'props' of undefined
When using a stateless functional component as you are (as opposed to a class based one) the component is called with ComponentName(props) - you can access props by updating the signature of the component to:
ActionButton (props) {
Which will allow you to access props.navLink etc inside the function.
Your ActionButton component is a dump component, so you have to pass the props as a argument to the function. Update your ActionButton component as shown below.
function ActionButton (props) {
return (
<div className="Action">
<button className="ActionButton">
<Link to={props.navLink}>
{props.text}
</Link>
</button>
</div>
);}
As you are new to React, read more about dump vs smart components here: https://medium.com/#thejasonfile/dumb-components-and-smart-components-e7b33a698d43

Facebook Create React App Build - Add Image As Prop Type

I have a component comment.js
export default function Comment (props) {
return (
<div className="comment-wrapper">
<img src={props.userImage} />
<p className="comment">{props.commentTitle}</p>
</div>
);
}
So I just simply want to have that component in the parent component as
<Comment userImage="IMAGE_LINK" commentTitle="BLAH BLAH" />
Again, I am using the Create-React-App build system from facebook. With that being said I know I can hard code an image using the following
<img src={require(`./images/MY-IMAGE.png`)} />
The code above works perfectly fine for the test image I am trying to load. However, when needed dynamically for the component the issue gets a bit more complex.
Now with the comment.js component above, I cannot do
<img src={require("./images" + {props.userImage})} />
I have taken a look at one thread on this site as well as reading this blog post on the issue and can still not come to a conclusion.
How can I handle image assets being passed as props to a component, in this case?
you can use import
// parent component
import MenuImage from '/img/menu.png'
<Comment image={MenuImage} commentTitle="Title"} />
then on Comment component
export default props => (
<img src={props.image} alt='' />
)

Adding tab dynamically upgradeElement

When I add a tab with react, its parent element is already upgraded. So calling upgradElement has no effect and the added tab doesn't work.
What solution, recreate all tabs with the container and upgrade it ? React just update DOM component in this case I need to dismount component ?
How about calling componentHandler.upgradeElement() or componentHandler.upgradeDom() in the componentDidUpdate phase of the specific component
componentDidUpdate() {
componentHandler.upgradeElement(this.refs.myElement);
//or componentHandler.upgradeDom('MaterialTabs');
}
EDIT 1 Tab Component
componentDidUpdate() {
componentHandler.upgradeDom();
}
newTab() {
this.setState({
newtab: 1
});
}
render() {
return (<div className="mdl-layout mdl-js-layout mdl-layout--fixed-header" key={this.state.newtab}>
<button onClick={this.newTab.bind(this)}>Add Tab</button>
<header className="mdl-layout__header">
<div className="mdl-layout__tab-bar mdl-js-ripple-effect">
<Link to="/tabtest" hash="#scroll-tab-1" className="mdl-layout__tab is-active">Tab 1</Link>
<Link to="/tabtest" hash="#scroll-tab-2" className="mdl-layout__tab">Tab 2</Link>
{ this.state.newtab ?
<Link to="/tabtest" hash="#scroll-tab-3" className="mdl-layout__tab">Tab 3</Link> : null}
</div>
</header>
<div className="mdl-layout__content">
<section className="mdl-layout__tab-panel is-active" id="scroll-tab-1">
<div className="page-content">Tab 1</div>
</section>
<section className="mdl-layout__tab-panel" id="scroll-tab-2">
<div className="page-content">Tab 2</div>
</section>
{ this.state.newtab ? <section className="mdl-layout__tab-panel" id="scroll-tab-3">
<div className="page-content">Tab 2</div>
</section> : null}
</div>
</div>);
}
I did some tests and could reproduce the problem. What helped was to put the key attribute on the root element of the tab component. When adding a new tab this key must change and react will throw away the component and rerender completly. This way all material-design-lite properties get lost and after calling upgradeDom or upgradeElement it works.
React and Material-Design-Lite
Material-Design-Lite source
From https://facebook.github.io/react/docs/component-api.html.
forceUpdate
void forceUpdate(
[function callback]
)
By default, when your component's state or props change, your component will re-render. However, if these change implicitly (eg: data deep within an object changes without changing the object itself) or if your render() method depends on some other data, you can tell React that it needs to re-run render() by calling forceUpdate().
Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child. React will still only update the DOM if the markup changes.
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient.
In order to highlight the most important part of Christian Steinmann's answer:
Give the surrounding .mdl-js-tabs div element the tabs count as the key attribute.
Whenever a tab is added, the key will change and React will rerender the whole tabs component. This will then the MDL upgrade.

Categories

Resources