如何在没有 Redux 的情况下处理应用程序状态?
在本文中,我们将学习如何在没有 Redux 的情况下处理状态。在任何 Web 应用程序中,有多种方法可以在不使用 redux 的情况下管理状态。在本文中,我们将通过useState() hook 学习状态管理。它是一个反应钩子,它返回两个值状态和一个函数,我们可以通过它改变状态,我们可以将初始状态作为参数,在下面的代码中它是一个空数组。每当状态更改时,组件都会重新渲染。让我们通过一个例子来理解这一点。在这个 web-app 中,我们将维护App组件中的状态(即任务数组),将任务数组传递给任务组件以正确的格式显示,并在任务组件的帮助下进行状态突变useState() 钩子提供的函数。
句法:
const [state,setState] = useState([]);
创建 React 应用程序并安装模块:
第 1 步:使用以下命令创建一个 React 应用程序。
npx create-react-app foldername
第 2 步:创建项目文件夹(即文件夹名称)后,使用以下命令移动到该文件夹:
cd foldername
第 3 步:使用以下命令运行开发服务器:
npm start
项目结构:它将如下所示。
实现:在相应的文件中添加以下代码。
App.js :在这个组件中,我们在 useState() 的帮助下创建了一个状态,并将其初始值设置为一个只有一个元素的数组。此外,我们还使用各自的名称将 props 传递给了Tasks组件。
Javascript
import { useState } from "react";
import "./App.css";
import Tasks from "./Component/Tasks";
function App() {
const [taskList, setTaskList] = useState([
{
title: "Submit DS assignment",
deadline: "1pm 10 March",
},
]);
return (
);
}
export default App;
Javascript
[e.target.name] : e.target.value
Javascript
import React, { useState } from "react";
import Task from "./Task";
const Tasks = ({ setTaskList, taskList }) => {
const inputStyles = {
border: "none",
borderBottom: "2px solid #9FE6A0",
outline: "none",
margin: "10px",
};
const [CurrentTask, setCurrentTask] = useState({});
let taskListDisplay = taskList.map((task, index) => {
return (
);
});
const handleClick = (e) => {
setTaskList([...taskList, CurrentTask]);
};
const handleChange = (e) => {
e.preventDefault();
setCurrentTask({
...CurrentTask,
[e.target.name]: e.target.value,
});
};
return (
Task-Web-App :
{taskListDisplay}
);
};
export default Tasks;
Javascript
import React from "react";
const Task = ({ deadline, title, index }) => {
return (
Task {index + 1}
{" "}
Title :
{title}
Deadline :
{deadline}
);
};
export default Task;
Javascript
import { useState } from "react";
import "./App.css";
import Songs from "./Component/Songs";
import Tasks from "./Component/Tasks";
function App() {
return (
);
}
export default App;
Javascript
import React, { useState,useEffect } from "react";
import axios from "axios";
const Songs = () => {
const [HitSongs, setHitSongs] = useState([]);
const [SingerName, setSingerName] = useState("Justin");
const inputStyles = {
border: "none",
borderBottom: "2px solid #9FE6A0",
outline: "none",
margin: "10px",
};
const fetchData = async () => {
var options = {
method: "GET",
url: "https://genius.p.rapidapi.com/search",
params: { q: `${SingerName}` },
headers: {
"x-rapidapi-host": "genius.p.rapidapi.com",
"x-rapidapi-key": "ffc2438edbmsh0a88b634e6e77a7p123125jsnfb163d4d72f7",
},
};
let data = await axios.request(options);
data = data.data.response.hits.slice(0, 5);
setHitSongs(data);
};
const handleClick = (e) => {
fetchData();
};
const handleChange = (e) => {
e.preventDefault();
setSingerName(e.target.value);
};
useEffect(() => {
fetchData();
}, []);
let displaySongs = HitSongs.map((song) => {
return (
{song.result.full_title}
);
});
return (
<>
Top 5 Hit songs :
{displaySongs.length === 0 ? (
<>
Fetching data ... Please wait 🙂
>
) : (
{displaySongs}
)}
>
);
};
export default Songs;
Tasks.js :在这个组件中,我们添加了一些基本样式,并将handleClick()和handleChange()连接到按钮和输入字段。我们已经使用该方法通过下面给出的语法动态更新对象属性。这使我们可以减少为不同的输入字段创建不同的 handleChange 函数的冗余。另外,请注意要使用此方法,输入字段必须具有name属性。 handleClick()函数负责改变状态并将当前任务添加到 App 的状态中。我们维护了一个组件状态CurrentTask它将帮助我们跟踪用户想要添加到列表中的任务。
Javascript
[e.target.name] : e.target.value
Javascript
import React, { useState } from "react";
import Task from "./Task";
const Tasks = ({ setTaskList, taskList }) => {
const inputStyles = {
border: "none",
borderBottom: "2px solid #9FE6A0",
outline: "none",
margin: "10px",
};
const [CurrentTask, setCurrentTask] = useState({});
let taskListDisplay = taskList.map((task, index) => {
return (
);
});
const handleClick = (e) => {
setTaskList([...taskList, CurrentTask]);
};
const handleChange = (e) => {
e.preventDefault();
setCurrentTask({
...CurrentTask,
[e.target.name]: e.target.value,
});
};
return (
Task-Web-App :
{taskListDisplay}
);
};
export default Tasks;
Task.js:这只是一个展示组件,它通过解构值/属性来显示任务详细信息。
Javascript
import React from "react";
const Task = ({ deadline, title, index }) => {
return (
Task {index + 1}
{" "}
Title :
{title}
Deadline :
{deadline}
);
};
export default Task;
网络应用程序的工作演示:
示例 2:在这个示例中,我们不会在 App 组件中维护状态,而是在其他一些子组件中维护状态,它将是Songs组件。我们将创建两个状态,一个存储歌手的名字,第二个将是用户输入的歌手的前 5 首热门歌曲的数组。我们将从 Rapid API 的开放 API 中获取数据,这将在 axios 的帮助下完成。下面讨论实现。
将 axios 安装为依赖项:
npm i axios
文件名 - App.js :由于我们不在此组件中维护应用程序状态,因此我们不需要此文件中的任何状态。
Javascript
import { useState } from "react";
import "./App.css";
import Songs from "./Component/Songs";
import Tasks from "./Component/Tasks";
function App() {
return (
);
}
export default App;
文件名——Songs.js:在这个组件中,我们默认将歌手的名字初始化为贾斯汀,这意味着它将在初始渲染时为贾斯汀获取数据。我们制作了一个fetchData函数,负责获取数据并更新Songs组件HitsSongs状态,该函数最初在应用加载时调用,以借助 useEffect 钩子获取 Justin 的热门歌曲。请注意,在为歌手获取热门歌曲时, params对象将保存歌手的姓名。当用户单击Find按钮时,我们可以重用这个fetchData函数,因为它是一个独立的函数,并且除了更新HitSongs状态之外,确实使用了任何其他数据。最后,我们将 onClick 和 onChange 处理程序连接到按钮和输入。
Javascript
import React, { useState,useEffect } from "react";
import axios from "axios";
const Songs = () => {
const [HitSongs, setHitSongs] = useState([]);
const [SingerName, setSingerName] = useState("Justin");
const inputStyles = {
border: "none",
borderBottom: "2px solid #9FE6A0",
outline: "none",
margin: "10px",
};
const fetchData = async () => {
var options = {
method: "GET",
url: "https://genius.p.rapidapi.com/search",
params: { q: `${SingerName}` },
headers: {
"x-rapidapi-host": "genius.p.rapidapi.com",
"x-rapidapi-key": "ffc2438edbmsh0a88b634e6e77a7p123125jsnfb163d4d72f7",
},
};
let data = await axios.request(options);
data = data.data.response.hits.slice(0, 5);
setHitSongs(data);
};
const handleClick = (e) => {
fetchData();
};
const handleChange = (e) => {
e.preventDefault();
setSingerName(e.target.value);
};
useEffect(() => {
fetchData();
}, []);
let displaySongs = HitSongs.map((song) => {
return (
{song.result.full_title}
);
});
return (
<>
Top 5 Hit songs :
{displaySongs.length === 0 ? (
<>
Fetching data ... Please wait 🙂
>
) : (
{displaySongs}
)}
>
);
};
export default Songs;
网络应用程序的工作演示: