我最近开始使用redux,因为我看到为整个应用程序使用单个状态树有许多潜在的好处。但是,我一直遇到一个问题。当我发送连续的商店更新时,后一个更新不知道前一个更新的商店更改。
例如,假设我有一个函数getCoffee(),并且getCoffee()填满了我的咖啡,然后在内部调用addCream()。装完咖啡后(我实际上不喜欢咖啡中的奶油),getCream()会添加奶油,但是不会知道getCoffee()会装满我的咖啡,最终我只会喝一杯奶油。
我已经集思广益了一些肯定可以使用的解决方案,但是我对如何分派多个操作(而后者知道更新的应用程序状态)更感兴趣。当前,我正在使用componentDidUpdate()检查是否有某些更改,然后进行相应的更新,但是对多个更新执行此操作会使事情变得复杂。
代码如下:
// Toggles display of search bar and calls getResults() if the input field is not empty this
handleSearch(event) {
const input = document.getElementById('recipe-name');
// Hides other search tools besides current search tool
this.hideSearchTools(event);
if(input.style.width === '0vw' || !input.style.width) {
// Renders searchbar
input.style.width = '70vw';
input.style.padding = '10px 15px'
input.style.boxShadow = '2px 2px 10px 1px rgba(0, 0, 0, .2)';
input.disabled = false;
} else if(input.style.width === '70vw' && !input.value) {
// Hides searchbar if input field is empty
input.style.width = '0vw';
input.style.padding = '10px 0px';
input.disabled = true;
} else {
// Perform search clear current query and hides searchbar
input.style.width = '0vw';
input.style.padding = '10px 0px';
input.value = '';
input.disabled = true;
if(this.props.recipesUI.results.recipes.length) {
// If there was previous search clears filters and sort slice of state
const nutrientFilters = [];
const foodTypeFilters = [];
const foodLabelFilters = [];
const sort = {
type: null,
criteria: null,
isNutrient: null
};
// Updates store with all filters and sort set to initial state
this.props.updateRecipesUI(Object.assign({}, this.props.recipesUI, { nutrientFilters, foodTypeFilters, foodLabelFilters, sort }));
};
this.getResults();
};
}
// Applies filters to a query sends off query to server, sorts if necessary and stores results in app state
getResults() {
let ui = { ...this.props.recipesUI };
let { sort, nutrientFilters, foodTypeFilters, foodLabelFilters } = ui;
if(!ui.query) {
return;
};
let path = "https://path/to/api?";
let query = 'q=' + ui.query.split(' ').join('%20');
path = path.concat(query);
// Helpers that build our query based on existing filters
path = path.concat(nutrientParams(nutrientFilters));
path = path.concat(typeParams(foodTypeFilters));
path = path.concat(labelParams(foodLabelFilters));
// Updates searching to true before request is initiated
this.props.updateRecipesUI(Object.assign({}, ui, {searching: true}));
fetch(`/api/recipes?path=${path}`)
.then(res => res.json())
.then(res => {
let results = {
...res,
currentPage: 0,
sortedRecipes: []
};
let { recipes } = results;
this.props.updateRecipesUI(Object.assign({}, ui, { results, searching: false }));
if(sort.criteria) {
this.sortRecipes();
};
});
}
// Initial App State as far as Recipes.js and children are concerned
const initState = {
recipesUI: {
results: {
recipes: [],
sortedRecipes: [],
q: null,
count: null,
currentPage: null
},
searching: false,
query: null,
nutrientFilters: [],
foodTypeFilters: [],
foodLabelFilters: [],
filtersToApply: [],
filtersToRemove: [],
sort: {
type: null,
criteria: null,
isNutrient: null
}
} }
当前,handleSearch()要么使搜索栏出现,隐藏它,要么将其隐藏并启动搜索(取决于仅作为输入元素的搜索栏的状态)。如果满足最后一个条件,则将调用getResults()来处理构造查询并将其发送给服务器的情况。在发送请求之前,将加载状态设置为true会覆盖handleSearch()末尾的状态重置。
谢谢!
编辑: 后者的存储区更新之所以能够继续保持先前的存储区更新的原因,可能是因为存储区尚未反映出handleSearch()中所做的更改时触发了第二个函数。