This commit is contained in:
Philippe Torrel
2026-08-25 13:20:44 +02:00
parent aabd029e7b
commit a13ce143f4
11 changed files with 4242 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,12 @@
import Button from './components/buttons/Button';
import ExampleComponent from './components/examples/ExampleComponent';
import ExampleCounter from './components/examples/ExampleCounter';
import ExampleLazy from './components/examples/ExampleLazy';
import ExampleMemoParent from './components/examples/ExampleMemoParent';
import ExampleUseCallback from './components/examples/ExampleUseCallback';
import ExampleUseCallbackRef from './components/examples/ExampleUseCallbackRef';
import ExampleUseMemo from './components/examples/ExampleUseMemo';
import ExampleUseRef from './components/examples/ExampleUseRef';
import InputAmount from './components/inputs/InputAmount';
// import FormContact from './components/forms/FormContact';
@@ -12,6 +18,18 @@ function App(props) {
return (
<>
<div className="container py-5">
<ExampleLazy />
<hr />
<ExampleUseCallbackRef />
{/* <hr />
<ExampleUseRef /> */}
<hr />
<ExampleUseCallback />
<hr />
<ExampleMemoParent />
<hr />
<ExampleUseMemo />
<hr />
<ExampleCounter />
<hr />
<InputAmount />

View File

@@ -0,0 +1,13 @@
import LazyComponent from './LazyComponent';
const ExampleLazy = (props) => {
// const { } = props;
return (
<div className="example-lazy">
<p>The content below will only be loaded when the component is needed</p>
<LazyComponent />
</div>
);
};
export default ExampleLazy;

View File

@@ -0,0 +1,15 @@
import { memo } from 'react';
const ExampleMemo = (props) => {
const { name } = props;
console.log('ExampleMemo is rendered');
return (
<div className="example-memo">
<p>Hello, {name}</p>
</div>
);
};
export default memo(ExampleMemo);
// rendert nur neu, wenn sich props (hier: name) verändert

View File

@@ -0,0 +1,34 @@
import { useState } from 'react';
import ExampleMemo from './ExampleMemo';
const ExampleMemoParent = (props) => {
// const { } = props;
const [name, setName] = useState('World');
const [counter, setCounter] = useState(0);
const names = ['Kahleel', 'Andreas', 'Ersin', 'Adel', 'Philippe'];
const handleClickCounter = (e) => {
setCounter((prevState) => prevState + 1);
};
const handleClickName = (e) => {
setName(names[Math.floor(Math.random() * names.length)]);
};
return (
<div className="example-memo-parent">
<ExampleMemo name={name} />
<p>Parent component is rendering: {counter}</p>
<button className="btn btn-dark mx-2 button-counter" onClick={handleClickCounter}>
Click to render and count up
</button>
<button className="btn btn-dark mx-2 button-name" onClick={handleClickName}>
Change name randomized
</button>
</div>
);
};
export default ExampleMemoParent;

View File

@@ -0,0 +1,64 @@
import { useCallback, useState } from 'react';
import ListItemProduct from './ListItemProduct';
const ExampleUseCallback = (props) => {
// const { } = props;
const [products, setProducts] = useState(
props.products || [
{ id: 1, title: 'Product 1', description: 'lorem ipsum', price: 10 },
{ id: 2, title: 'Product 2', description: 'ipsum lorem', price: 20 },
{ id: 3, title: 'Product 3', description: 'lorem dolor', price: 30 },
],
);
const handleClick = useCallback((e, productId) => {
setProducts((prevProducts) => {
return prevProducts.map((product) => {
if (product.id === productId) {
return { ...product, price: parseFloat(product.price + 1) };
} else {
return product;
}
});
});
}, []); // <-- leere dependency- Array sorgt dafür, dass die callback funktion und somit der Event-Handler nur einmalig ausgeführt/angelegt wird.
// EventHandler =================
// const handleClick = (e, productId) => {
// console.log('Product clicked:', productId);
// setProducts((prevProducts) => {
// return prevProducts.map((product) => {
// if (product.id === productId) {
// return { ...product, price: parseFloat(product.price + 1) };
// } else {
// return product;
// }
// });
// });
// };
// show me the render stuff.
console.log(JSON.stringify(products));
return (
<div className="example-use-callback">
{products && products.length > 0 ? (
<ul className="list-group list-group-flush list-products">
{products.map((product) => (
<ListItemProduct
key={`product-${product.id}`}
{...product}
onClick={(e) => {
handleClick(e, product.id);
}}
/>
))}
</ul>
) : (
<p>no products</p>
)}
</div>
);
};
export default ExampleUseCallback;

View File

@@ -0,0 +1,53 @@
import { useCallback, useState } from 'react';
import { FaPen } from 'react-icons/fa6';
const ExampleUseCallbackRef = (props) => {
// const { } = props;
const [title, setTitle] = useState('');
const [editMode, setEditMode] = useState(true);
// const inputRef = useRef(null); // Rückgabewert ist ein Objekt mit Eigenschaft current { current: HTMLElement}
const inputRef = useCallback((input) => {
input && input.focus();
console.log(input);
}, []);
const handleChangeTitle = (e) => {
setTitle(e.target.value);
};
const handleClickEditMode = (e) => {
setEditMode((prevState) => !prevState);
console.log(inputRef);
};
return (
<div className="example-use-ref">
<div className="row">
<div className="col-11">
{editMode ? (
<input
type="text"
name="title"
className="form-control input-title"
value={title}
onChange={handleChangeTitle}
ref={inputRef}
/>
) : (
<span style={{ padding: '6px 12px', display: 'inline-block' }}>{title}</span>
)}
</div>
<div className="col">
<button className="btn btn-dark button-edit-mode" onClick={handleClickEditMode}>
<FaPen />
<span className="visually-hidden">Edit Mode</span>
</button>
</div>
</div>
</div>
);
};
export default ExampleUseCallbackRef;

View File

@@ -0,0 +1,59 @@
import { useMemo, useState } from 'react';
const ExampleUseMemo = (props) => {
// const { } = props;
const [products, setProducts] = useState([
{ id: 1, name: 'Product 1', price: 10 },
{ id: 2, name: 'Product 2', price: 20 },
{ id: 3, name: 'Product 3', price: 30 },
]);
const [text, setText] = useState('');
const productsAmount = useMemo(() => {
console.log('Calculating the number of products');
return products.length;
}, [products]);
// EventHandler
const handleChangeText = (e) => {
setText(e.target.value);
};
// Functions
// const getNumberProducts = () => {
// console.log('Calculating the number of products');
// return products.length;
// };
return (
<div className="example-use-memo">
{products && products.length > 0 ? (
<ul className="list list-group mb-3">
{products.map((product, idx) => (
<li key={`list-item-product-${idx}`} className="list-group-item list-item-product">
{product.name} - ${product.price.toFixed(2)}
</li>
))}
</ul>
) : (
<p>Loading...</p>
)}
<p>Number of products in the list: {productsAmount}</p>
<h4>Input to rerender component:</h4>
<input
type="text"
name="text"
className="form-control input-text my-3"
placeholder="Input text to rerender"
value={text}
onChange={handleChangeText}
/>
<p>
<strong>Text:</strong> {text}
</p>
</div>
);
};
export default ExampleUseMemo;

View File

@@ -0,0 +1,59 @@
import { useEffect, useRef, useState } from 'react';
import { FaPen } from 'react-icons/fa6';
const ExampleUseRef = (props) => {
// const { } = props;
const [title, setTitle] = useState('');
const [editMode, setEditMode] = useState(true);
const inputRef = useRef(null); // Rückgabewert ist ein Objekt mit Eigenschaft current { current: HTMLElement}
useEffect(() => {
console.log('Full component rendered');
if (inputRef.current) {
console.log('ref: ', inputRef.current);
inputRef.current.focus();
}
return () => {};
}, [editMode]);
const handleChangeTitle = (e) => {
setTitle(e.target.value);
};
const handleClickEditMode = (e) => {
setEditMode((prevState) => !prevState);
console.log(inputRef);
};
return (
<div className="example-use-ref">
<div className="row">
<div className="col-11">
{editMode ? (
<input
type="text"
name="title"
className="form-control input-title"
value={title}
onChange={handleChangeTitle}
ref={inputRef}
/>
) : (
<span style={{ padding: '6px 12px', display: 'inline-block' }}>{title}</span>
)}
</div>
<div className="col">
<button className="btn btn-dark button-edit-mode" onClick={handleClickEditMode}>
<FaPen />
<span className="visually-hidden">Edit Mode</span>
</button>
</div>
</div>
</div>
);
};
export default ExampleUseRef;

View File

@@ -0,0 +1,14 @@
const LazyComponent = (props) => {
// const { } = props;
// Simulate a slow network connection
const wait = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
wait(3000);
return (
<div className="lazy alert alert-info">
<h4>I was loaded late!</h4>
<p>This text only appears after the code for this component has been loaded.</p>
</div>
);
};
export default LazyComponent;

View File

@@ -0,0 +1,14 @@
const ListItemProduct = (props) => {
const { title, description, price, children } = props;
return (
<li onClick={props.onClick} className="list-item-product list-group-item">
<h3>{title}</h3>
<p>{children || description}</p>
<p>
Price: <strong>${price.toFixed(2)}</strong>
</p>
</li>
);
};
export default ListItemProduct;