react中使用构建缓存
Today in this story we are going to build an app using React and Redux. The function of this application is that allows user to keep track of their shopping list.
今天,在这个故事中,我们将使用React和Redux构建一个应用程序。 该应用程序的功能是允许用户跟踪其购物清单。
Before getting into the topic, you have to know the basic fundamentals of redux to develop this application.
在开始讨论本主题之前,您必须了解redux的基本基础知识才能开发此应用程序。
Let’s see what are the functions we are going to add for this application to perform various tasks.
让我们看看我们要为该应用程序执行各种任务而添加的功能。
- You can able to add an item to the shopping list. 您可以将商品添加到购物清单。
- You can able to mark an item in the basket. 您可以在篮子中标记物品。
- You can remove an item in the shopping list. 您可以从购物清单中删除商品。
- You can able to delete the entire shopping list. 您可以删除整个购物清单。
前端 (Frontend)
The user interface contains a text input in which user can able to input the shopping item and then they click an add button to add an item in their list. The clear button is used to remove all the items in their list. If a user taps on an item it will add into the basket and the colour will change to grey. If they tap again it will remove the single item in their list.
用户界面包含一个文本输入,用户可以在其中输入购物商品,然后单击添加按钮以在其列表中添加商品。 清除按钮用于删除列表中的所有项目。 如果用户点击某个项目,它将添加到购物篮中,并且颜色将变为灰色。 如果他们再次点击,它将删除列表中的单个项目。
动作 (Actions)
Go to src folder and create an another folder called store. Inside that create two files actions.js and reducer.js.
转到src文件夹并创建另一个名为store的文件夹。 在其中创建两个文件actions.js和reducer.js 。
// actions.js
export const actionCreators = {
addToList: data => ({ type: "ADD_TO_LIST", payload: data }),
addToBasket: data => ({ type: "ADD_TO_BASKET", payload: data }),
removeItem: data => ({ type: "REMOVE_ITEM", payload: data }),
clearItems: () => ({ type: "CLEAR_ITEMS" })
};
We need to assign a value or id for each item to add or remove from the list/basket. The clearItem down not need any data because it will need to set the array in our store back to an empty array.
我们需要为每个项目分配一个值或ID ,以将其添加到列表/购物篮中或从中删除。 clearItem向下不需要任何数据,因为它将需要将我们商店中的数组设置回空数组。
新增项目 (Adding an item)
Now create a reducer.js inside our store folder. Then setup our initial state like this.
现在,在我们的商店文件夹中创建一个reducer.js 。 然后像这样设置我们的初始状态。
const initialState = {
items: []
}
Now let’s create a reducer and then to perform the task to adding a new item to the item array in our store.
现在让我们创建一个化简器,然后执行将新项目添加到我们商店中的item数组的任务。
export default (state = initialState, action) => {
switch (action.type) {
case "ADD_TO_LIST":
return {
...state,
items: [
...state.items,
{
value: action.payload,
inBasket: false
}
]
};
default:
return state;
}
};
Using the keyword export default to export our reducer file so we didn’t require a function name. The reducer function takes the initial state and the current action to be sent to the store.
使用关键字export default导出我们的化简文件,因此我们不需要函数名。 减速器功能将初始状态和当前操作发送到商店。
Before we assign any actions to the store, the value of the store is empty items array at the initial state. The action.type value in the ADD_TO_LIST is returns the current state of the list and then append the new item to the current state.items array.
在将任何操作分配给商店之前,商店的值在初始状态下为空项目数组。 ADD_TO_LIST中的action.type值返回列表的当前状态,然后将新项追加到当前state.items数组。
You might be little confusing about the redux concepts, we just created a custom state that is immutable.
您可能对redux概念有些困惑,我们只是创建了一个不可变的自定义状态。
清除物品 (Clearing an item)
At this moment you will now have an idea how to handle the function for clearing the items.
现在,您将了解如何处理清除项目的功能。
case "CLEAR_ITEMS": {
return {
items: []
};
}
Now we just created an another case to our reducer to return the new state object with an item as an empty array.
现在,我们为reducer创建了另一个案例,以将带有一个项目的新状态对象作为空数组返回。
将商品添加到购物篮 (Adding item to the basket)
Now we are going to add an item into the array and remove the white item in the array. Adding an item into the basket means we have to re-assign the inBasket property and set the item to true.
现在我们将添加一个项目到数组中,并删除数组中的白色项目。 将商品添加到购物篮中意味着我们必须重新分配inBasket属性并将该商品设置为true 。
The function to handle the update of an array in an item looks like this.
处理项目中数组更新的功能如下所示。
function updateObjectInArray(array, action) {
return array.map((item, index) => {
if (index !== action.index) {
// This isn't the item we care about - keep it as-is
return item
}
// Otherwise, this is the one we want - return an updated value
return {
...item,
...action.item
}
})
}
Add the above function to the reducer.js file but outside of the reducer and then make a slight changes for properly updating the inBasket to true.
将以上函数添加到reducer.js文件中,但在reducer之外,然后进行一些更改,以将inBasket正确更新为true 。
return {
...item,
inBasket: true
}
For marking an item in our basket let’sadd the following code.
要在我们的购物篮中标记商品,请添加以下代码。
case "ADD_TO_BASKET":
return {
...state,
items: updateObjectInArray(state.items, action)
};
The updateObjectInArray function will return the updated items in an array.
updateObjectInArray函数将返回数组中的更新项 。
从列表中删除一个项目 (Remove an item from the list)
This is similar to how we have add an item in the list with the couple of variation looks like this.
这类似于我们在列表中添加具有几个变体的项目的方式,如下所示。
function removeItem(array, action) {
return array.filter((item, index) => index !== action.index)
}
And then add the function as a private function to the reducer.js .
然后将该函数作为私有函数添加到reducer.js中 。
Our REMOVE_ITEM case will look like this now.
我们的REMOVE_ITEM情况现在看起来像这样。
case "REMOVE_ITEM":
return {
...state,
items: removeItemFromList(state.items, action)
};
Our entire reducer.js look like this now.
我们整个的reducer.js现在看起来像这样。
const initialState = {
items: []
};
const updateObjectInArray = (array, action) => {
return array.map((item, index) => {
if (index !== action.payload) {
return item;
}
return {
...item,
inBasket: true
};
});
};
const removeItem = (array, action) => {
return array.filter((item, index) => index !== action.payload);
};
export default (state = initialState, action) => {
switch (action.type) {
case "ADD_TO_LIST":
return {
...state,
items: [
...state.items,
{
value: action.payload,
inBasket: false
}
]
};
case "ADD_TO_BASKET":
return {
...state,
items: updateObjectInArray(state.items, action)
};
case "REMOVE_ITEM":
return {
...state,
items: removeItem(state.items, action)
};
case "CLEAR_ITEMS": {
return {
items: []
};
}
default:
return state;
}
};
添加项目组件 (Adding item components)
Now this is the most important part to build our component to dispatch our actions. For adding an item you need an input that keep track of an item and a button when it is clicked it will dispatch an action addToList with the current value of the input.
现在,这是构建我们的组件以调度我们的行动的最重要部分。 要添加项目,您需要一个输入,该输入跟踪一个项目和一个单击时的按钮,它将分派带有输入当前值的操作addToList 。
We are using hooks and redux library to import dispatch actions. Your component will look like this.
我们正在使用钩子和redux库来导入调度动作。 您的组件将如下所示。
import React, { useState } from "react";
import { Button } from "react-bootstrap";
import { useDispatch } from "react-redux";
import { actionCreators } from "../../store/actions";
export default function AddItem() {
const dispatch = useDispatch();
const [input, setInput] = useState("");
const handleInputChange = event => {
return setInput(event.target.value);
};
const handleSubmit = () => {
dispatch(actionCreators.addToList(input));
setInput("");
};
const handleClear = () => {
dispatch(actionCreators.clearItems());
};
return (
<div>
<input
className="input"
placeholder="Add item..."
value={input}
onChange={handleInputChange}
/>
<Button className="button" variant="outline-dark" onClick={handleSubmit}>
Add
</Button>
<Button className="button" variant="outline-dark" onClick={handleClear}>
Clear
</Button>
</div>
);
}
Finally we setup the input that make use of the useState hooks to track and clear that value. The handleInputChange will update the value for each event when the button is pressed.
最后,我们设置使用useState挂钩的输入,以跟踪和清除该值。 当按下按钮时, handleInputChange将更新每个事件的值。
查看购物清单 (Viewing The Shopping List)
Now we have to build the component to display the current list of the items. Again we have to import the useDispatch from the react-redux library using useSelector hooks to get values out of the store.
现在,我们必须构建该组件以显示项目的当前列表。 同样,我们必须使用useSelector钩子从react-redux库中导入useDispatch ,以使值脱离存储。
import React from "react";
import { ListGroup } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import { actionCreators } from "../../store/actions";
export default function ShoppingList() {
const dispatch = useDispatch();
const items = useSelector(state => state.items);
const addItemToBasket = index => {
dispatch(actionCreators.addToBasket(index));
};
const removeItemFromList = index => {
dispatch(actionCreators.removeItem(index));
};
return (
<ListGroup className="m-4" variant="flush">
{items.map((item, index) => {
return item.inBasket ? (
<ListGroup.Item
key={index}
variant="dark"
onClick={() => removeItemFromList(index)}
>
{item.value}
</ListGroup.Item>
) : (
<ListGroup.Item
key={index}
variant="danger"
onClick={() => addItemToBasket(index)}
>
{item.value}
</ListGroup.Item>
);
})}
</ListGroup>
);
}
When we are mapping the item into the array it changes the colour to grey. The addItemToBasket and removeItemFromList will take the index of the selected item and dispatch the data with their relevant action.
当我们将项目映射到数组时,它会将颜色更改为灰色。 addItemToBasket和removeItemFromList将获取所选项目的索引,并通过其相关动作调度数据。
最终模型 (Final Model)
Finally, we have to go to our index.js and make some changes. we have to import createStore and provider from the redux library to generate a store from the redux. You index need to look like this.
最后,我们必须转到我们的index.js并进行一些更改。 我们必须从redux库中导入createStore和provider以通过redux生成商店。 您的索引需要看起来像这样。
import React from "react";
import { render } from "react-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import App from "./App";
import reducer from "./store/reducer";
const store = createStore(reducer);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
结论 (Conclusion)
I hope you enjoyed a lot and find something new today. Now you will be able to create an app in React using Redux library.
希望您今天过得愉快,并找到新的东西。 现在,您将能够使用Redux库在React中创建一个应用程序。
Have fun and Thanks for reading!
玩得开心,感谢您的阅读!
翻译自: https://medium.com/front-end-weekly/build-a-shopping-list-app-using-react-be92f57aafe9
react中使用构建缓存