[英]How to integrate redux inside a react.js app?
while I'm trying to apply redux_react with functional code I have a problem with.subscribe() it runs multiple times every state update = (count of all previous updates + 1) how can I re-render the UI only once.. every state update当我尝试将 redux_react 与功能代码一起应用时,我遇到了 .subscribe() 的问题,它每次 state 更新 =(所有先前更新的计数 + 1)运行多次state 更新
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- Redux -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js" integrity="sha512-1/8Tj23BRrWnKZXeBruk6wTnsMJbi/lJsk9bsRgVwb6j5q39n0A00gFjbCTaDo5l5XrPVv4DZXftrJExhRF/Ug==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- react & react-dom -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel: transpiles JSX code into Common JS - that browser can understand -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="app"></div>
<!-- Babel JSX code -->
<script type="text/babel">
// =============================== Redux (State management) =============================================
// action types
const [ADD_TODO, REMOVE_TODO, TOGGLE_TODO] = ["ADD_TODO", "REMOVE_TODO", "TOGGLE_TODO"]
const [ADD_GOAL] = ["ADD_GOAL"]
// action creators
const addTodo = todo => ({
type: ADD_TODO,
todo
})
const removeTodo = id => ({
type: REMOVE_TODO,
id
})
const toggleTodo = id => ({
type: TOGGLE_TODO,
id
})
const addGoal = goal => ({
type: ADD_GOAL,
goal
})
// Reducers
const todosReducer = (state=[], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, action.todo]
case REMOVE_TODO:
return state.filter((s) => s.id !== action.id)
case TOGGLE_TODO:
return state.map((s) => (s.id == action.id)? {...s, complete: !s.complete} : s)
default:
return state
}
}
const goalsReducer = (state=[], action) => {
switch (action.type) {
case ADD_GOAL:
return [...state, action.goal]
default:
return state
}
}
// Redux Store
const store = Redux.createStore(
// Root Reducer
Redux.combineReducers({
todos: todosReducer,
goals: goalsReducer
})
)
// =============================== React App =============================================
// Components
const List = ({items, removeItem, toggle}) => {
return (
<ul>
{
items.map((itm) =>
<li key={itm.id}>
<span id={itm.id} onClick={(toggle)? toggle : null} style={{textDecoration: (itm.complete)? 'line-through' : ''}}>
{itm.text}
</span>
<button id={itm.id} onClick={removeItem}> X </button>
</li>
)
}
</ul>
)
}
const Todos = ({items}) => {
const newTodoInput = React.useRef()
// add new
const handleAddTodo = () => {
const newTodo = newTodoInput.current
// Redux <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// dispatch the addTodo action --> to update Redux State
// ** No need to lift-up handleAddTodo() to all parents :)
store.dispatch(
addTodo({
id: (new Date()).getTime().toString(36),
text: newTodo.value,
complete: false
})
)
newTodo.value = ""
}
// remove
const handleRemoveTodo = (e) => {
store.dispatch(removeTodo(e.target.id))
}
// toggle
const handleToggle = (e) => {
store.dispatch(toggleTodo(e.target.id))
}
return (
<div>
<h3>My Todos:</h3>
<div>
<input type="text" placeholder="new todo ..." ref={newTodoInput} />
<button onClick={handleAddTodo}>Save</button>
</div>
<List items={items} removeItem={handleRemoveTodo} toggle={handleToggle} />
</div>
)
}
const Goals = ({items}) => {
return (
<div>
<h3>My Goals:</h3>
<List items={items} />
</div>
)
}
const App = ({store}) => {
const [todos, setTodos] = React.useState([])
const [goals, setGoals] = React.useState([])
// Redux <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
store.subscribe(() => {
console.log(store.getState())
const newState = store.getState()
setTodos(newState.todos)
setGoals(newState.goals)
})
return (
<div>
<Todos items={todos} />
<Goals items={goals} />
</div>
)
}
// Root
const root = ReactDOM.createRoot(document.getElementById("app"))
root.render(
<App store={store} />
)
</script>
</body>
</html>
how can i make the state updates without subscribing on all previous updates如何在不订阅所有先前更新的情况下进行 state 更新
You can avoid to use subscribe with react, here is the recommended way:你可以避免使用 subscribe 和 react,这里是推荐的方式:
subscribe
您可以将 redux 与反应挂钩使用以避免使用subscribe
To track redux update when state change you can use useSelector
which is made for要在 state 更改时跟踪useSelector
更新,您可以使用为
Then you avoid to use subscribe
to your state change, useSelector do it for you然后你避免使用subscribe
你的 state 更改,使用选择器为你做
Do not forget to use Provider
from react-redux
不要忘记使用react-redux
中的Provider
Here is a small example这是一个小例子
const Goals = () => {
const items = useSelector(goalsSelector)
return (
<div>
<h3>My Goals:</h3>
<List items={items} />
</div>
)
}
const App = ({store}) => {
return (
<Provider store={store}>
<div>
<Todos />
<Goals />
</div>
</Provider>
)
}
useEffect
如果您仍想在 react function 组件中订阅,则必须使用useEffect
With your current implementation on every renderer you subscribe again to redux.使用您当前在每个渲染器上的实现,您再次订阅 redux。
Here you subscribe only when the component is mounted then you unsubscribe when you unmount it在这里,您仅在安装组件时订阅,然后在卸载组件时取消订阅
const App = ({store}) => {
const [todos, setTodos] = React.useState([])
const [goals, setGoals] = React.useState([])
// Redux <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
React.useEffect(() => {
const unsubscribe = store.subscribe(() => {
console.log(store.getState())
const newState = store.getState()
setTodos(newState.todos)
setGoals(newState.goals)
})
return unsubscribe;
}, [])
return (
<div>
<Todos items={todos} />
<Goals items={goals} />
</div>
)
}
Use useSelector
or the connect()
API to read from redux state instead of subscribing to the store manually.使用useSelector
或connect()
API 从 redux state 读取,而不是手动订阅商店。 useSelector
and useDispatch
are the relevant hooks to dispatch actions and access state inside function components. useSelector
和useDispatch
是派发动作和访问 function 组件中的 state 的相关钩子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.