React + Redux = React + Context
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
我知道,已经有很多文章在讨论是否应该用 Context 替换 Redux,以及替换的利弊等等。但我认为这篇文章不属于这类讨论。
这纯粹是为了好玩😁。不过,你也可以在你的个人项目中尝试一下😉。
希望您已安装 NodeJS、npm 和 npx。
首先,我们来设置一个基本的 React 模板。进入你想进行实验的目录。运行,npx create-react-app fooapp
更改应用程序目录cd fooapp。
现在启动应用程序npm start。我希望应用程序已经启动并在您的浏览器中打开http://localhost:3000/。
在src下创建一个名为store 的文件夹。cd src && mkdir store
store在.index.js和 .目录下创建两个文件handlers.js
在index.js文件下store。我们将创建一个上下文。
/** index.js **/
import React from "react";
import PropTypes from "prop-types";
// Import all handlers
import * as handlers from "./handlers";
// Default state
const initialState = { todos:[] };
// Export the context
export const Context = React.createContext({ state: initialState, handlers });
// Export the provider
export const Provider = ({ children }) => {
// This will be our global state
const [state, setState] = React.useState(initialState);
// Modify our hanlders with state and setState
// Thanks Jose for this one 👍
const modHandlers = Object.keys(handlers).map(key => handlers[key](state, setState))
// Feed the state and modified handlers to the provider
return (
<Context.Provider value={{ state, handlers: modHanlders }}>
{children}
</Context.Provider>
);
};
Provider.propTypes = {
children: PropTypes.children.isRequired
};
让我们创建处理程序来添加/删除待办事项列表中的事项。在store/handlers.js……
/* handlers.js*/
export const addTodo = (state, setState) => todo => {
state.todos.push(todo);
setState({ ...state });
}
export const removeTodo = (state, setState) => i => {
delete state.todos[i];
setState({ ...state });
};
更新src/index.js文件。添加以下内容。
// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import Todo from "./components/Todo";
import { Provider } from "./store";
function App() {
return (
<Provider>
<div className="App">
<h2 className="apptitle">Todo List</h2>
<Todo />
</div>
</Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
如果出现错误请不要担心,我们会进行更新。
components在目录下创建一个文件夹src。将这三个文件添加到该文件夹中Todo.js,TodoField.js& TodoItem.js。
在你的components/Todo.js文件中创建一个组件,用于存放待办事项列表。
// components/Todo.js
import React from "react";
import TodoItem from "./TodoItem";
import TodoField from "./TodoField";
import { Context } from "../store";
const Todo = props => {
// Get the state from Context using useContext hook
const { state } = React.useContext(Context);
return (
<div>
<TodoField />
<ul>
{state.todos.map((todo, i) => (
<TodoItem value={todo} index={i} />
))}
</ul>
</div>
);
};
export default Todo;
错误现在应该已经消失了。
在您的代码中components/TodoField.js添加以下代码。
// components/TodoField.js
import React from "react";
import { Context } from "../store";
const TodoField = () => {
const [todo, setTodo] = React.useState(null);
// Import the handlers from context
const { handlers } = React.useContext(Context);
// Handles form and other things
const handleSubmit = e => {
e.preventDefault();
// Add the todo to the store
handlers.addTodo(todo);
};
const handleChange = e => {
setTodo(e.target.value);
};
// Form with field and submit button
return (
<form onSubmit={handleSubmit} onChange={handleChange}>
<input type="text" value={todo} required />
<input type="submit" value="Add Todo" />
</form>
);
};
export default TodoField;
在您的代码中components/TodoItem.js添加以下代码。
// components/TodoItem.js
import React from "react";
import { Context } from "../store";
const TodoItem = ({ value, index }) => {
const { handlers } = React.useContext(Context);
const removeFromTodo = e => {
handlers.removeTodo(index);
};
return (
<li>
{value} <button onClick={removeFromTodo}>x</button>
</li>
);
};
export default TodoItem;
所有数据均来自同一存储库,并使用处理程序进行操作。
在 Lodash 中,您可以使用 get 和 set 方法来操作复杂的 JSON 对象。
附注:上述方法也可以处理基于 Promise 的异步操作。
实现代码已上传至codesandbox。
祝您编码愉快!👩💻👨💻.... 😀
