Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Button.css */
.btn {
background-color: #38c78b;
border: 1px solid #1f6e4d;
}
14 changes: 14 additions & 0 deletions src/Button.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";
import "./Button.css";

class Button extends React.Component {
render() {
return (
<button className="btn" onClick={this.props.onClick} type="button">
{this.props.children}
</button>
);
}
}

export default Button;
13 changes: 13 additions & 0 deletions src/CustomButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";

class CustomButton extends React.Component {
render() {
return (
<button style={{ backgroundColor: this.props.color }} type="button">
{this.props.children}
</button>
);
}
}

export default CustomButton;
16 changes: 16 additions & 0 deletions src/Greeting.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";

class Greeting extends React.Component {
render() {
return (
<div>
<h1>
Hello {this.props.firstName} {this.props.lastName}
</h1>
<h2>Good to see you!</h2>
</div>
);
}
}

export default Greeting;
23 changes: 23 additions & 0 deletions src/GreetingImage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";

/**
* props:
* name: string
* withImage: boolean
*/
class GreetingImage extends React.Component {
render() {
const { name, withImage } = this.props;

return (
<div>
<h1>Good Morning {name}</h1>
{withImage && (
<img src="https://api.dicebear.com/9.x/adventurer/svg" alt="avatar" />
)}
</div>
);
}
}

export default GreetingImage;
20 changes: 20 additions & 0 deletions src/GreetingTime.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

/**
* props:
* name: string
* isMorning: boolean
*/
class GreetingTime extends React.Component {
render() {
const { name, isMorning } = this.props;

return (
<div>
{isMorning ? <h1>Good Morning {name}</h1> : <h2>Goodbye {name}</h2>}
</div>
);
}
}

export default GreetingTime;
30 changes: 30 additions & 0 deletions src/PersonList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";

export class PersonList extends React.Component {
/**
* Renders a list of persons.
* @note Using array indices as keys is generally not recommended because:
* 1. It can cause performance issues when the list order changes (additions/removals)
* 2. It may lead to unexpected behavior or bugs with component state
* 3. React specifically warns against this practice in its documentation
* 4. If the list is re-ordered, indices will change, causing unnecessary re-renders
*
* Ideally, use a unique and stable identifier from each item as the key instead.
* Like here we could use person.name as the key.
*/
render() {
const persons = [
{ name: "John Doe" },
{ name: "Georges Abitbol" },
{ name: "Kevin McGregor" },
];

return (
<ul>
{persons.map((person, index) => (
<li key={index}>{person.name}</li>
))}
</ul>
);
}
}
60 changes: 40 additions & 20 deletions src/main.jsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,52 @@
import { createRoot } from "react-dom/client";

const user = {
id: 1,
name: "John Doe",
};
import Button from "./Button";
import CustomButton from "./CustomButton";
import Greeting from "./Greeting";
import GreetingImage from "./GreetingImage";
import GreetingTime from "./GreetingTime";
import { PersonList } from "./PersonList";

function capitalize(name) {
return name.toUpperCase();
function handleClick() {
alert("Congratulation! You clicked a button!");
}

function getAvatarUrl(user) {
return `https://api.dicebear.com/9.x/adventurer/svg?seed=${user.name}${user.id}`;
}

const greeting = (
const greetings = (
<div>
<h1>Hello {capitalize(user.name)}</h1>
<img src={getAvatarUrl(user)} alt={`${user.name}'s avatar`} />
<Greeting firstName="John" lastName="Doe" />
<Greeting firstName="Georges" lastName="Abitbol" />
<Greeting firstName="Edgar" lastName="KNP" />
</div>
);

const header = (
<header>
<img src="https://picsum.photos/id/237/200/300" alt="picsum" />
{greeting}
</header>
const customButton = (
<CustomButton color="red">
<span>Click me</span>
</CustomButton>
);

const root = createRoot(document.getElementById("root"));
const button = <Button onClick={handleClick}>Click me</Button>;

const greetingMorning = <GreetingTime name="John" isMorning={true} />;
const greetingEvening = <GreetingTime name="Jane" isMorning={false} />;

root.render(header);
const greetingWithImage = <GreetingImage name="Edgar" withImage={true} />; // <GreetingImage name="Edgar" withImage />
const greetingWithoutImage = <GreetingImage name="Toto" withImage={false} />;

const root = createRoot(document.getElementById("root"));
root.render(
<>
{greetings}
---
{customButton}
{button}
---
<PersonList />
---
{greetingMorning}
{greetingEvening}
---
{greetingWithImage}
{greetingWithoutImage}
</>,
);