<BrowserRouter>
<Switch>
<Route exact path="/">
<Main
mockData={this.props.mockData}
onClickOfferCardTitle={this.handleOfferCardTitleClick}
/>
</Route>
<Route exact path="/dev-property/:title" >
{/* component={Property} */}
{(props) => <Property {...props}/>}
</Route>
</Switch>
</BrowserRouter>
Inside function-component:
const Property = (props) => {
const propertyID = props.match.params.id;
const arr = props.mockData.offerCard;
return (
<React.Fragment>
<div>{propertyID.type}</div>
</React.Fragment>
)
}
may be:
const Property = ({match: {params: {id: propertyID}}, mockData: {offerCard: arr}}) => {
const currentItem = arr.find(({id}) => id === propertyID);
const {id, badge, type, bedrooms, people, hostBadge, ownerAvatar, images, rating, price, pricePer, title, facilities} = currentItem;
return (
<React.Fragment>
...
<div>{type}</div>
...
</React.Fragment>
)
}
(props.children - тут children - служебное неизменяемое название)
<Title>
<h1>title</h1>
</Title>
export default (props) => {
return (
<title>
{props.children}
</title>
)
}
<Title render={() => (<h1>header</h1>)} />
export default (props) => {
return (
<title>
{props.render()}
</title>
)
}
conditional render props:
<Header render={
(isMobile) => (
isMobile
? <h1>Для котиков</h1>
: <h1>Товары для котиков</h1>
)
} />
// componet:
const isMobile = true; // Какое-то жуткое вычисление мобильных на JavaScript
export default (props) => (
<header>
{props.render(isMobile)}
</header>
);
(когда нужно сильно изменить компонент, полностью изменить его детей и т.д.)
//APP
export default () => {
return (
<React.Fragment>
<Header>
<h1>Товары для котиков</h1>
</Header>
<Main>
<ul className="products">
{
products.map((product) => (
<li key={product.id}>
<ProductNew className="product--in-list" product={product} />
</li>
))
}
</ul>
</Main>
</React.Fragment>
);
};
//PRODUCT
export default ({className, product}) => (
<article className={`product ${className}`}>
{product.type && <mark>{product.type}</mark>}
<h3><a href="#">{product.title || `Артикул ${product.id}`}</a></h3>
<p>{product.price} ₽</p>
</article>
);
//PRODUCT-NEW
import Product from "./product.jsx";
export default (props) => {
// 1. конкатинируем все классы
const className = `product--new ${props.className || ``}`;
// 2.удаляем тот класс, который пришел из оригинальных пропсов
const restProps = Object.assign({}, props)
delete restProps.className;
// 3.юзаем (передаем) className где хранятся все сконкатенированные классы
return (
<Product className={className} {...restProps} />
);
};
/*
Если бы в проекте был транспилятор (Babel),
можно было бы писать так:
const {className, ...restProps} = props;
<Product className={`product--new ${className}`} {...restProps} />
*/
(когда в контейнере собираем логику по отрисовке дочерних компонентов)
//APP
export default () => {
return (
<React.Fragment>
<Header>
<h1>Товары для котиков</h1>
</Header>
<Main>
<ProductList products={products} />
</Main>
</React.Fragment>
);
};
//PRODUCT-LIST - C O N T A I N E R
import Product from "./product.jsx";
import ProductNew from "./product-new.jsx";
import ProductSale from "./product-sale.jsx";
import {Type} from "../data.js";
export default ({products}) => {
const getComponentByType = (type, product) => {
switch (type) {
case Type.SALE:
return;
case Type.NEW:
return;
default:
return;
}
};
return (
<ul className="products">
{
products.map((product) => (
<li key={product.id}>
<Product product={product} />
</li>
))
}
</ul>
);
};
(если нужно кастомизировать компонент, допустим, рендерить что-то в зависимости от 2х и больше пропсов) (если мы хотим расшарить между компонентами логику - это HOC) (обычно, называется с приставкой with-)
//APP
const App = () => {
return (
<form className="form">
<p>
<Toggle>Включи меня</Toggle>
</p>
<p>
<InputHelp placeholder="Заполни меня" />
</p>
</form>
);
}
ReactDOM.render(<App />, document.getElementById(`root`));
//INPUT
import {withActiveFlag} from "./withActiveFlag.jsx";
const InputHelp = (props) => {
const {isActive, onActiveChange, ...restProps} = props;
return (
<React.Fragment>
<input
type="text"
onFocus={onActiveChange}
onBlur={onActiveChange}
{...restProps}
/>
{isActive && (
<span className="help">
Подсказка по заполнению
</span>
)}
</React.Fragment>
);
}
// THIS IS HOW WE USE HOC
// JUST PASS INTO THE HOC DESIRED FUNCTION
export default withActiveFlag(InputHelp);
//withActiveFlag - H O C
export const withActiveFlag = Component => props => {
const [isActive, setActive] = React.useState(false);
const handleActiveChange = () => setActive(!isActive);
return (
<Component
{...props}
isActive={isActive}
onActiveChange={handleActiveChange}
/>
);
}