<button onClick={() => setModal('раз окно')}>1</button>
<button onClick={() => setModal('два окно')}>2</button>
<button onClick={() => setModal('три окно')}>3</button>
...
<Modal display={modal === 'раз окно'}>...</Modal>
<Modal display={modal === 'два окно'}>...</Modal>
<Modal display={modal === 'три окно'}>...</Modal>
Подскажите самые простые учебники / статьи / видео курсы по React, где нормальным языком доступно объясняется.
На офф сайте читал и мануалы и практическое руководство, тяжело очень дается и порой не понтно что к чему и зачем.
фразы оттуда навроде "Подъём состояния в родительский компонент — обычное дело при рефакторинге React-компонентов." лишь отпугивают новичков вроде меня
C javascript знаком на базовом уровне
fetch('https://jsonplaceholder.typicode.com/todos/1')
1
.const [data, setData] = useState(null);
{data.map(item => (
null
метод map
? - погуглите, разберитесь. Ну и замените null
на []
. const values = [ 2, 3, 5, 7, 11, 13, 17, 19, ... ];
useEffect(() => {
const index = values.indexOf(граничное_значение_второго_инпута);
setVal2(values
.slice(...(val1 > граничное_значение_первого_инпута ? [ index ] : [ 0, index ]))
.reduce((val, n) => Math.abs(val - val2) < Math.abs(n - val2) ? val : n)
);
}, [ val1, val2 ]);
1 + Math.max(0, ...articles.map(n => n.id))
const getId = (() => {
let id = 0;
return () => ++id;
})();
onResize = () => {
this.setState(() => ({
/* ... */
}));
}
componentDidMount() {
window.addEventListener('resize', this.onResize);
this.onResize();
}
componentWillUnmount() {
window.removeEventListener('resize', this.onResize);
}
onChange = {(event, userItem)=>handleChange(event, userItem)}
onChange={e => handleChange(e, userItem)}
.onChange={handleChange.bind(userItem)}
,function handleChange(e) {
console.log('userItem', this);
console.log('value', e.target.value);
}
const group = (arr, key) =>
arr.reduce((acc, n) => (
(acc[n[key]] = acc[n[key]] || []).push(n),
acc
), {});
const groupItemKeys = [ 'kurs', 'contract', 'credit' ];
const groupedData = useMemo(() => {
return Object.entries(group(data, 'country'));
}, [ data ]);
<tbody>{groupedData.map(([ country, items ], i) =>
<tr>
<td>{i + 1}</td>
<td>{country}</td>
{groupItemKeys.map(k =>
<td>{items.map(n => <div>{n[k]}</div>)}</td>
)}
</tr>)}
</tbody>
const groupedData = useMemo(() => {
return Object.values(group(data, 'country'));
}, [ data ]);
<tbody>{groupedData.map((n, i) => n.map((m, j) =>
<tr>
{!j && <React.Fragment>
<td rowSpan={n.length}>{i + 1}</td>
<td rowSpan={n.length}>{m.country}</td>
</React.Fragment>}
{groupItemKeys.map(k => <td>{m[k]}</td>)}
</tr>))}
</tbody>
const rowsData = useMemo(() => {
return Object
.values(group(data, 'country'))
.flatMap((items, i) => items.map((n, j) => (j
? []
: [ i + 1, n.country ].map(m => [ m, items.length ])
).concat(groupItemKeys.map(k => [ n[k] ]))));
}, [ data ]);
<tbody>{rowsData.map(n =>
<tr>{n.map(m => (
<td rowSpan={m[1]}>{m[0]}</td>))}
</tr>)}
</tbody>
const Figure = ({ type, ...props }) => <div className={type} {...props}></div>;
class App extends React.Component {
state = {
types: [ 'circle', 'square', 'triangle' ],
figures: [],
}
add(type) {
this.setState(({ figures }) => ({
figures: [ ...figures, type ],
}));
}
render() {
const { types, figures } = this.state;
return (
<div>
<div>
{types.map(n => <Figure type={n} onClick={() => this.add(n)} />)}
</div>
<div>
{figures.map(n => <Figure type={n} />)}
</div>
</div>
);
}
}
function Preloader({ Tag = 'h1', children }) {
return (
<Tag className={s.wrapper}>
<div className={s.preloader}></div>
{children}
</Tag>
);
}
<div className="App">
<Preloader>hello, world!!</Preloader>
<Preloader Tag="h2">fuck the world</Preloader>
</div>
const AccordionItem = ({ title, opened, toggle, children }) => (
<div>
<button onClick={toggle}>{title}</button>
{opened && children}
</div>
);
const Accordion = ({ items }) => {
const [ opened, setOpened ] = useState(null);
return (
<div>
{items.map((n, i) => (
<AccordionItem
title={n.title}
opened={i === opened}
toggle={setOpened.bind(null, i === opened ? null : i)}
>
<p>{n.text}</p>
</AccordionItem>
))}
</div>
);
};
AddProduct={this.props.addProduct}
this.props.addProduct(product);
state = {
value: 0,
options: [ 'Не отмечено', 'Отмечено' ],
}
onChange = ({ target: t }) => {
this.setState(() => ({
value: +t[t.dataset.stateAttr],
}));
}
render() {
const { value, options } = this.state;
return (
<div>
<select
value={value}
onChange={this.onChange}
data-state-attr="value"
>
{options.map((n, i) => <option value={i}>{n}</option>)}
</select>
<br />
<label>
<input
type="checkbox"
checked={value}
onChange={this.onChange}
data-state-attr="checked"
/>
{options[value]}
</label>
</div>
);
}
function Card(props) {
return (
<div>
{props.children}
</div>
);
}
function App() {
return (
<div>
<Card />
<Card>
<CircleTopik />
</Card>
<Card />
</div>
);
}
function Card({ showCircle }) {
return (
<div>
{showCircle ? <CircleTopik /> : null}
</div>
);
}
function App() {
return (
<div>
<Card />
<Card showCircle />
<Card />
</div>
);
}
React.memo затрагивает только изменения пропсов. Если функциональный компонент обёрнут в React.memo и использует useState, useReducer или useContext, он будет повторно рендериться при изменении состояния или контекста.
<div className="todoListMain"> <div className="header">
.todoListMain.header input {
.todoListMain
и .header
куда потерялся? Ну и с остальными стилями косяк тот же. массивСДанными.map((n, i) => {
const Component = i % через_сколько_там_надо_чередовать_компоненты
? КомпонентРаз
: КомпонентДва;
return <Component {...n} />;
})
function Ranges(props) {
const onChange = ({ target: t }) => {
const index = +t.dataset.index;
const value = +t.value;
const values = props.values.map((n, i) => i === index ? value : n);
if (props.max >= values.reduce((acc, n) => acc + n, 0)) {
props.onChange(values);
}
};
return (
<div>
{props.values.map((n, i) => (
<div>
<input
type="range"
data-index={i}
max={props.max}
value={n}
onChange={onChange}
/>
{n}
</div>
))}
</div>
);
}