"react": "^16.4.0",
import React, { Component, PropTypes } from 'react';
Note:React.PropTypes
has moved into a different package since React v15.5. Please use the prop-types library instead.
Просто нужно еще чтобы компонент `SortableElement ` принял все пропсы.
const SortableItem = SortableElement((props) => (
<ElementItem {...props} />
));
onScroll = e => {
if (e.target.offsetHeight + e.target.scrollTop === e.target.scrollHeight) {
/*
* здесь предпринимаете действия, имеющие своим результатом
* демонстрацию дополнительного контента
*/
}
}
<div onScroll={this.onScroll}>
...
const Image = ({ url }) => (
<div>
<img src={url} />
</div>
);
class App extends React.Component {
state = {
items: [],
}
componentDidMount() {
fetch('https://api.kai-zer.ru/dev/method/products.getAll')
.then(r => r.json())
.then(r => {
this.setState({
items: r.response.items,
});
});
}
render() {
return (
<div>
{this.state.items.map(n => <Image {...n.image} />)}
</div>
);
}
}
Поиск работает только с первого раза. Потом, когда состояние должно вернуться после фильтрации, этого почему-то не происходит.
class App extends React.Component {
state = {
people: this.props.people,
};
handeSearch = e => {
const search = e.target.value.toLowerCase();
this.setState((state, { people }) => ({
people: people.filter(n => n.name.toLowerCase().includes(search)),
}));
}
render() {
return (
<div className="contacts">
<input
type="text"
className="search-field"
onChange={this.handeSearch}
/>
<ul className="contacts-list">
{this.state.people.map(n => <Person key={n.id} {...n} />)}
</ul>
</div>
);
}
}
ReactDOM.render(
<App people={Peoples} />,
document.getElementById('root')
);
в shouldComponentUpdate nextState.items почему-то равно всегда this.state.items
let items = this.state.items;
items.push( undefined );
let items = [ ...this.state.items, undefined ]
class App extends React.Component {
state = {
selected: {},
groups: [
[
[ 'value_a1', 'value_a2', 'value_a3' ],
[ 'value_b1', 'value_b2', 'value_b3' ],
[ 'value_c1', 'value_c2', 'value_c3' ],
],
[
[ 'value_a1', 'value_b1', 'value_c1' ],
[ 'value_a2', 'value_b2', 'value_c2' ],
[ 'value_a3', 'value_b3', 'value_c3' ],
],
],
}
onChange = (e, groupIndex, itemIndex) => {
const selectedGroup = this.state.groups[groupIndex][itemIndex];
const selectedInfo = this.state.selected[groupIndex] || [];
this.setState({
selected: {
...this.state.selected,
[groupIndex]: e.target.checked
? selectedInfo.concat(selectedGroup)
: selectedInfo.filter(n => !selectedGroup.includes(n))
},
});
}
render() {
const { selected, groups } = this.state;
const matched = (selected[0] || []).filter(n => {
return groups.every((group, i) => (selected[i] || []).includes(n));
});
return (
<div>
{groups.map((group, groupIndex) => (
<ul>
{group.map((item, itemIndex) => (
<li>
<input
type="checkbox"
onChange={(e) => this.onChange(e, groupIndex, itemIndex)}
/>
{item.map(val => <span>{val}</span>)}
</li>
))}
</ul>
))}
<div>
{matched.map(val => <span>{val}</span>)}
</div>
</div>
);
}
}
Comment
- судя по имени и по коду, он должен рендерить один комментарий, а у вас массив. Наверное, тут нужен ещё один компонент - список комментариев.const Comment = ({ general, job, address }) => (
<li>
<div>first name: {general.firstName}</div>
<div>last name: {general.lastName}</div>
<div>company: {job.company}</div>
<div>address: {address.country}, {address.city}, {address.street}</div>
</li>
);
const CommentList = ({ comments }) => (
<ul>
{comments.map(n => <Comment {...n} />)}
</ul>
);
ReactDOM.render(
<CommentList comments={comments} />,
document.getElementById('root')
);
Приходит массив объектов, и в объекте надо менять свойствоenabled: true
соответственно в другом объекте это свойство нужно заменить наfalse
.
.highlighted {
color: red;
font-weight: bold;
font-size: 1.5em;
}
class App extends React.Component {
state = {
items: [ 'aaa', 'aa1', 'ab1', 'zzz', '00!', 'lorem ipsum dolor...' ],
search: '',
}
render() {
const { items, search } = this.state;
const regex = RegExp(search, 'g');
const replacement = '<span class="highlighted">$&</span>';
return (
<div>
<input value={search} onChange={e => this.setState({ search: e.target.value })} />
{search &&
<ul>
{items.filter(n => n.includes(search)).map(n =>
<li dangerouslySetInnerHTML={{ __html: n.replace(regex, replacement) }} />
)}
</ul>}
</div>
);
}
}
const Input = ({ label, ...props }) => (
<div>
<label>
{label}
<input {...props} />
</label>
</div>
);
class App extends React.Component {
state = {
from: 'Москва',
to: 'Питер',
}
onChange = ({ target: { value, name } }) => {
this.setState(() => ({
[name]: value,
}));
}
swap = () => {
this.setState(({ from, to }) => ({
from: to,
to: from,
}));
}
render() {
return (
<div>
<button onClick={this.swap}>swap</button>
<Input label="откуда" value={this.state.from} name="from" onChange={this.onChange} />
<Input label="куда" value={this.state.to} name="to" onChange={this.onChange} />
</div>
);
}
}
this.state = {loadworksheep: false};
this.setState({loadWorksheep: true});
w
должна быть большой или маленькой? Вы бы определились.const worksheetLoaderPage = ( WorksheetSelector );
WorksheetSelector
---> <WorksheetSelector />
Если есть другой способ по нажатию кнопки рендерить другую страницу, то буду крайне рад услышать.
toggleRow(index) {
this.setState(({ productsList, history }) => ({
productsList: productsList.map((n, i) => i === index
? { ...n, deleted: !n.deleted }
: n
),
history: [
...history,
{
currentDateInfo: new Date().toLocaleDateString(),
deleted: !productsList[index].deleted,
index,
},
],
}));
}
<ul className="list-group">
{this.state.history.map(n =>
<li className="list-group-item">
Row {n.index} {n.deleted ? 'deleted' : 'restored'} at {n.currentDateInfo}
</li>
)}
</ul>
Как я думал сделать:
По клику наdelete
делать поля Name и Idvisibility: none
и в стейте сделать переменнуюisDeleted: true
, если true то рендерить кнопку Restor'а, по клику на нее полям возвращатьvisibility
.
const ProductItem = ({ product, toggleRow }) => {
return (
<tr>
<th>{product.deleted || product.id}</th>
<td>{product.deleted || product.name}</td>
<td>
<button onClick={toggleRow}>
{product.deleted ? 'Restore' : 'Delete'}
</button>
</td>
</tr>
);
};
class Products extends React.Component {
state = {
products: [ 'Apple', 'Peanut', 'Tomato', 'Cucumber', 'Banana', 'Lemon' ].map((n, i) => ({
id: i + 1,
name: n,
deleted: false,
})),
}
toggleRow(index) {
this.setState(({ products }) => ({
products: products.map((n, i) => i === index
? { ...n, deleted: !n.deleted }
: n
),
}));
}
render() {
return (
<table>
<thead>
<tr>
<th>#</th>
<th>Product Name</th>
<th>Delete / Restore</th>
</tr>
</thead>
<tbody>
{this.state.products.map((n, i) => (
<ProductItem
key={n.id}
product={n}
toggleRow={() => this.toggleRow(i)}
/>
))}
</tbody>
</table>
);
}
}
deleteRow={() => this.deleteRow(i)}
deleteRow(index) {
const productsList = [...this.state.productsList];
productsList.splice(index, 1);
this.setState({
productsList,
});
}
modalRun = (modalState) => {
this.setState((prevState) => {
return {
modal: {
...prevState.modal,
state: modalState,
},
};
});
}
connect(mapStateToProps, null)(Authentication);
you have to pass formReducer under 'form' key