This commit is contained in:
3899
05_react/unterricht/tag52/01_react-app-performance/package-lock.json
generated
Normal file
3899
05_react/unterricht/tag52/01_react-app-performance/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 />
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user