Я пытаюсь разработать приложение, которое показывает фотографии с unsplash, которые затем отображаются в приложении. Поскольку я должен был отсортировать результаты и вызвать вторую конечную точку, я использую Redux-Thunk. Мне нужно сохранить предыдущие поиски в переменной, а затем иметь возможность отображать данные для определенного ключевого слова, не отправляя второй запрос API.
Я запрещаю второй вызов API в моем компоненте SearchBar:
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = {
term: ""
};
this.onInputChange = this.onInputChange.bind(this);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onInputChange(event) {
this.setState({
term: event.target.value
});
}
onFormSubmit(event) {
event.preventDefault();
const { categories } = this.props;
if (!categories.includes(this.state.term.toLowerCase())) {
this.props.setCategory(this.state.term);
this.props.fetchPhotos(this.state.term);
} else {
alert(`You've already searched for ${this.state.term.toLowerCase()}`);
}
this.setState({
term: ""
});
}
render() {
return (
<form onSubmit={this.onFormSubmit}>
<input
placeholder="Type your request"
className="form-control"
value={this.state.term}
onChange={this.onInputChange}
/>
</form>
);
}
}
const mapDispatchToProps = dispatch => {
return bindActionCreators({ fetchPhotos, setCategory }, dispatch);
};
const mapStateToProps = state => {
return {
categories: state.categories
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(SearchBar);
Однако, поскольку я использую асинхронные действия, у меня возникают проблемы с хранением данных.
Создатели действий:
const unsplashClient = new Unsplash({
applicationId:
"id",
secret: "secret",
callbackUrl: "callback"
});
export const fetchingPhotos = payload => ({
type: FETCHING_PHOTOS,
payload
});
export const setPhotos = payload => ({
type: SET_PHOTOS,
payload
});
export const fetchPhotos = term => dispatch => {
dispatch(fetchingPhotos());
return unsplashClient.search
.photos(term, 1, 20)
.then(toJson)
.then(json => {
dispatch(setPhotos(json));
dispatch(fetchingPhotos(false));
});
};
export const unsplash = term => dispatch => {
dispatch(fetchingPhotos());
setTimeout(() => {
dispatch(fetchPhotos(term));
return Promise.resolve();
}, 1000);
};
Разбавление:
export default function(state = initialState, action) {
switch (action.type) {
case FETCHING_PHOTOS:
return {
...state,
isFetching: true
};
case SET_PHOTOS:
console.log(action, state);
return {
...state,
isFetching: false,
items: action.payload.results,
store: Object.assign({}, state, action.payload.results)
};
case SET_SORT:
return {
...state,
sortKey: action.sortKey,
sortDirection: action.sortDirection
};
default:
return state;
}
}
И компонент, который получает данные:
class PhotoList extends Component {
constructor(props) {
super(props);
this.state = {
sortKey: "",
sortDirection: "descending"
};
this.handleClick = this.handleClick.bind(this);
this.handleKeyChange = this.handleKeyChange.bind(this);
this.handleDirectionChange = this.handleDirectionChange.bind(this);
}
renderPhotos() {
console.log(this.props);
const { items: photos } = this.props;
if (!photos) {
return;
}
return photos.map(photo => {
const url = photo.urls.small;
const id = photo.id;
const alt = photo.description;
return <SinglePhoto url={url} key={id} id={id} alt={alt} />;
});
}
handleClick() {
const { dispatch } = this.props;
const { sortDirection, sortKey } = this.state;
dispatch(sort(sortDirection, sortKey));
}
handleKeyChange(e) {
this.setState({
...this.state,
sortKey: e.target.value
});
}
handleDirectionChange(e) {
this.setState({
...this.state,
sortDirection: e.target.value
});
}
render() {
return (
<div>
<div>
<div>
<label htmlFor="sortKey">Sort Key:</label>
<select
name="sortKey"
id="sortKey"
value={this.state.sortKey}
onChange={this.handleKeyChange}
>
<option value="">Select property</option>
<option value="created_at">created_at</option>
<option value="likes">likes</option>
<option value="downloads">downloads</option>
</select>
</div>
<label htmlFor="sortDirection">Sort Direction:</label>
<select
name="sortDirection"
id="sortDirection"
value={this.state.sortDirection}
onChange={this.handleDirectionChange}
>
<option value="descending">Descending</option>
<option value="ascending">Ascending</option>
</select>
<button type="button" onClick={this.handleClick}>
SORT
</button>
</div>
<div className="grid">{this.renderPhotos()}</div>
</div>
);
}
}
const mapStateToProps = state => {
return {
items: getSortedPhotosSelector(state),
sortKey: state.photos.sortKey,
sortDirection: state.photos.sortDirection,
store: state.store
};
};
export default connect(mapStateToProps)(PhotoList);
Метод Object.assign()
, к сожалению, не работает должным образом: я думал, что он будет хранить все искомые данные, а не только текущий искомый.
Как я могу хранить данные и иметь доступ к ним позже? Моей первой мыслью было использовать localStorage, однако, это также кажется неправильным.