Relay和Redux有什么不同
Redux
它是一个用于管理和集中应用程序状态的开源JavaScript库。它通常与诸如React或Angular之类的库一起用于构建用户界面。它是JavaScript应用程序的状态容器。React Redux是Redux的官方React绑定。它允许React组件从Redux存储中读取数据并将操作分派到存储以更新数据。Redux通过提供一种合理的方式来管理状态的一致性数据流模型,从而有助于扩展应用程序。
Redux有三个主要组件:
- Store: 它包含组件的状态,可以传递给应用程序中的其他组件。
- Actions: 它包含可以在存储中的状态上执行的操作。
- Reducers: 这些是纯函数,包含需要对状态执行的操作。
语法
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer);
export default store;
安装和配置Redux的步骤
步骤1:安装React应用程序
使用以下命令创建一个React应用程序:
npx create-react-app redux-example
步骤2: 现在进入项目目录:
cd redux-example
步骤3:安装 React Redux
使用以下命令安装 Redux 库:
npm install redux react-redux
步骤4:导入所需组件:
import { useSelector, useDispatch } from 'react-redux';
步骤5: 在 src 文件夹内创建一个名为 redux 的新文件夹。
mkdir src/redux
步骤6: 在 redux 文件夹中创建一个名为 actions.js 的新文件。
touch src/redux/actions.js
步骤7: 在 redux 文件夹中创建一个新文件 reducers.js 。
touch src/redux/reducers.js
步骤8: 在 redux 文件夹中创建一个名为 store.js 的新文件。
touch src/redux/store.js
项目结构
它将如下所示:
步骤9: 现在,我们将定义Redux的动作。
- actions.js 文件
export const increment = () => {
return {
type: 'INCREMENT'
};
};
export const decrement = () => {
return {
type: 'DECREMENT'
};
};
步骤10: 现在,我们将定义在Redux中使用的reducers。
- reducers.js 文件
const initialState = {
count: 0
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return {
...state,
count: state.count + 1
};
case 'DECREMENT':
return {
...state,
count: state.count - 1
};
default:
return state;
}
};
export default reducer;
步骤11: 为Redux创建存储器。
- store.js 文件:
import { createStore } from 'redux';
import reducer from './reducers';
const store = createStore(reducer);
export default store;
- App.js 文件
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './redux/actions';
function App() {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={() => dispatch(increment())}>
Increment
</button>
<button onClick={() => dispatch(decrement())}>
Decrement
</button>
</div>
);
}
export default App;
- index.js 文件用于将 App 组件与 Redux Provider 包装起来:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import App from './App';
import './index.css';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
- 运行应用程序的步骤: 从项目的根目录下使用以下命令运行应用程序:
npm start
输出: 现在打开你的浏览器并访问 http://localhost:3000/ ,你将看到以下输出
因此,我们使用React Redux创建了一个简单的计数器应用程序,通过创建2个actions,在Redux Store中存储状态,然后使用Reducers生成输出。
Relay
Relay 是一个用于React的数据管理库,可以使用 GraphQL 来获取和更新数据。它与GraphQL API紧密配合,通过使用声明式方法和称为 GraphQL fragments 的概念来优化数据获取。React Relay基本上是一个 框架 ,用于构建基于GraphQL的React应用程序。它使得无论您的React应用程序有多少个组件,数据获取的管理都变得简单。
语法
import { RelayEnvironmentProvider } from 'react-relay/hooks';
安装和配置中继的步骤
步骤1:安装一个React应用
使用以下命令创建一个React应用。
npx create-react-app relay-example
步骤2: 现在,我们需要从GraphQL服务器获取数据。为此,我们将使用 fetch API 请求来自 GitHub GraphQL API 的一些数据,并将其用作服务器。
要开始,我们需要一个用于GitHub API的 身份验证密钥令牌 。按照以下步骤操作:
- 转到 github.com/settings/tokens
- 确保选择了最新的 repo(仓库)权限范围
- 生成一个唯一的令牌并储存以供您使用
步骤3: 导航到您项目的主目录
cd relay-example
步骤4: 现在,我们将从React中获取GraphQL。我们可以使用 fetchGraphQL 函数在React应用中获取一些数据。在 App.js 文件中编写以下代码:
async function fetchGraphQL(text, variables) {
const REACT_APP_GITHUB_AUTH_TOKEN =
process.env.REACT_APP_GITHUB_AUTH_TOKEN;
// Fetch data from GitHub's GraphQL API:
const response =
await fetch('https://api.github.com/graphql', {
method: 'POST',
headers: {
Authorization: `bearer ${REACT_APP_GITHUB_AUTH_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: text,
variables,
}),
});
// Get the response as JSON
return await response.json();
}
export default fetchGraphQL;
步骤5: 将Relay添加到应用程序中。
使用以下命令安装react-relay的依赖项:
npm install --save relay-runtime react-relay
npm install --save-dev relay-compiler babel-plugin-relay
OR
yarn add relay-runtime react-relay
yarn add --dev relay-compiler babel-plugin-relay
步骤6: 创建一个GraphQL模式
在你的项目根目录中创建一个名为schema.graphql的文件。从GitHub的GraphQL API文档中复制模式,或者使用公共GraphQL API中的示例模式。
步骤7: 修改你的package.json
文件,使得我们在启动应用程序时首先运行编译器:
{
"name": "relay-example",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-relay": "^15.0.0",
"react-scripts": "5.0.1",
"relay-runtime": "^15.0.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "npm run relay && react-scripts start",
"build": "npm run relay && react-scripts build",
"relay": "relay-compiler",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"relay": {
"src": "./src/",
"schema": "./schema.graphql",
"language": "javascript"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"babel-plugin-relay": "^15.0.0",
"relay-compiler": "^15.0.0"
}
}
- 创建一个新文件 RelayEnvironment.js ,并在其中编写以下代码:
import { Environment, Network, RecordSource, Store }
from 'relay-runtime';
import fetchGraphQL from './fetchGraphQL';
// Relay passes a "params" object with the query name and text.
// So we define a helper function
// to call our fetchGraphQL utility with params.text.
async function fetchRelay(params, variables) {
console.log(`fetching query {params.name}
with{JSON.stringify(variables)}`);
return fetchGraphQL(params.text, variables);
}
// Export a singleton instance of Relay
//Environment configured with our network function:
export default new Environment({
network: Network.create(fetchRelay),
store: new Store(new RecordSource()),
});
步骤8: 现在,我们将使用Relay获取查询。在 App.js 文件中编写以下代码:
import React from 'react';
import './App.css';
import graphql
from 'babel-plugin-relay/macro';
import {
RelayEnvironmentProvider,
loadQuery,
usePreloadedQuery,
} from 'react-relay/hooks';
import RelayEnvironment from './RelayEnvironment';
const { Suspense } = React;
// Define a query
const RepositoryNameQuery = graphql`
query AppRepositoryNameQuery {
repository(owner: "facebook", name: "relay") {
name
}
}
`;
// Immediately load the query as our app starts.
const preloadedQuery =
loadQuery(RelayEnvironment, RepositoryNameQuery, {
/* query variables */
});
// Inner component that reads the preloaded
// query results via `usePreloadedQuery()`.
function App(props) {
const data =
usePreloadedQuery(RepositoryNameQuery, props.preloadedQuery);
return (
<div className="App">
<header className="App-header">
<p>{data.repository.name}</p>
</header>
</div>
);
}
// <RelayEnvironmentProvider> tells child components
// how to talk to the current
// Relay Environment instance
// <Suspense> specifies a fallback in case a child suspends.
function AppRoot(props) {
return (
<RelayEnvironmentProvider environment={RelayEnvironment}>
<Suspense fallback={'Loading...'}>
<App preloadedQuery={preloadedQuery} />
</Suspense>
</RelayEnvironmentProvider>
);
}
export default AppRoot;
- 运行应用程序的步骤: 编译Relay查询
运行Relay编译器以为您的查询生成构件:
npm run relay
从项目的根目录中使用以下命令运行应用程序:
npm start
输出: 现在打开你的浏览器,访问 http://localhost:3000/ ,你将会看到以下输出:
最初,当数据正在抓取时,屏幕上会显示 Loading 。一旦数据被获取,上述输出将会显示。
Relay和Redux的区别:
属性 | Relay | Redux |
---|---|---|
目的 | 用于数据获取和缓存的GraphQL客户端框架。 | 用于存储和管理应用程序状态的React状态管理库。 |
数据获取 | 使用GraphQL查询和片段的声明式数据获取。 | 使用动作和reducers进行手动数据获取。 |
存储结构 | 基于GraphQL模式的分层存储结构。 | 使用reducers管理状态的扁平存储结构。 |
性能 | 使用GraphQL进行优化的数据获取和缓存。 | 性能取决于应用程序设计和使用模式。 |
组件绑定 | 使用容器组件和高阶组件进行数据绑定。 | 使用useDispatch()和useSelector()等hooks处理状态。 |
复杂度 | 可能较复杂,需要对GraphQL有一定的了解。 | 相对较简单,可以在较小的应用程序中轻松使用。 |
结论
选择Relay还是Redux取决于您的应用程序的特定需求。如果您正在使用GraphQL,并且需要高效的数据获取和处理能力,应该使用Relay。如果您需要更灵活的状态管理,则应该使用Redux。