[英]React-Redux. After changing state by useDispatch, components not updating by useSelector
[英]How to retrieve data from Redux store using functional components and avoiding useSelector & useDispatch
我正在 React-Redux 中嘗試使用 Todo App; 運行 store、actions、reducer 和 Addodo 組件; 但一直堅持顯示待辦事項:
如果我的 initialState=[] 如何從商店檢索數據?
店鋪:
import { createStore } from 'redux';
import rootReducer from '../reducer';
export const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store
我的減速機:
const initialState = [];
const todos = (state = initialState, action) => {
switch(action.type) {
// Aca va tu codigo;
case 'AddTodo':
return [...state, action.payload];
case 'RemoveTodo':
return state.filter(todo => todo.id !== action.payload)
case 'ToInProgress':
return state.map((todo) =>
todo.id === action.payload ? { ...todo, status: "InProgress" } : todo
);
case 'ToDone':
return state.map((todo) =>
todo.id === action.payload ? { ...todo, status: "Done" } : todo
);
default:
return state
}
}
export default todos;
應用程序.js:
import React from 'react'
import { Route } from "react-router-dom"
import {Provider} from 'react-redux'
import store from './store/index'
import Nav from '../src/components/Nav/Nav'
import Home from '../src/components/Home/Home'
import AddTodo from '../src/components/AddTodo/AddTodo'
import TodoDetail from '../src/components/TodoDetail/TodoDetail'
import './App.css';
export function App() {
return (
<React.Fragment>
<Provider store={store}>
<Nav />
<Route exact path="/" component={Home} />
<Route path="/add" component={AddTodo} />
<Route path="/edit/:id" component={TodoDetail} />
</Provider>
</React.Fragment>
);
}
export default App;
主頁.js:
import React from 'react';
import Todos from '../Todos/Todos'
import './home.css'
export function Home() {
return (
<div className="todosContainer">
<div>
<Todos status="Todo"/>
<label>TODO</label>
</div>
<div>
<Todos status='InProgress' />
<label>InProgress</label>
</div>
<div>
<Todos status='Done'/>
<label>Done</label>
</div>
</div>
)
};
export default Home;
這是 AddTodo:
export function AddTodo() {
const [state,setState]=React.useState({
title:"",
description:"",
place:"",
date:"",
})
function handleChange(e){
const value=e.target.value;
setState({
...state,
[e.target.name]:value
})
}
function handleSubmit(e){
e.preventDefault();
store.dispatch(addTodo({
place:state.place,
title:state.title,
date:state.date,
description:state.description
})) // parameters "id" & "status" loaded in Actions.
setState({title:"",
description:"",
place:"",
date:"",})
}
return (
<div className="todoContainer">
<form id="formulario"onSubmit={handleSubmit} >
<label>
Title
<input type="text" name="title" value={state.title} onChange={handleChange} />
</label>
<label>
Description
<textarea type="text" name="description" value={state.description} onChange= {handleChange}/>
</label>
<label>
Place
<input type="text" name="place" value={state.place} onChange={handleChange}/>
</label>
<label>
Date
<input type="text" name="date" value={state.date} onChange={handleChange}/>
</label>
<button className="boton" type="submit" onClick={addTodo}>Agregar</button>
</form>
</div>
)
};
function mapDispatchToProps(dispatch){
return{
addTodo: todo => dispatch(addTodo(todo))
}
}
export default connect(mapDispatchToProps)(AddTodo)
現在,我想在 Todos 組件中展示,每個 Todos “標題”,仍然不知道如何執行它:
export function Todos(data) {
return (
<div className="todoDetail">
<h4>{data.title}</h4>
</div>
)
};
function mapStateToProps(state) {
return {
data: state.title,
};
}
export default connect(mapStateToProps)(Todos)
你在找useSelector鈎子。
不要在功能組件中使用store.getState()
。 此外,您不需要connect
功能組件,使用useDispatch鈎子。
從商店獲取值將是這樣的:
const todos = useSelector(store => store.items);
很奇怪,他們(代碼訓練營)要求你使用函數組件,然后不允許你使用 React 鈎子,使函數組件如此吸引人。 不用擔心,您仍然可以使用舊的connect
高階組件將您的 redux 狀態和可調度操作注入傳遞給組件的 props。
您在AddToDo
組件中AddToDo
問題。 您將mapDispatchToProps
傳遞到將傳遞mapStateToProps
回調的connect
HOC。 您也沒有使用剛剛映射的注入的addTodo
操作。 你幾乎不需要直接訪問store
對象來分派動作,使用 React 組件/鈎子。
export function AddTodo() {
const [state, setState] = React.useState({
title:"",
description:"",
place:"",
date:"",
});
function handleChange(e) {
const { value } = e.target;
setState(prevState => ({ // <-- use functional state update
...prevState,
[e.target.name]:value
}));
}
function handleSubmit(e) {
e.preventDefault();
this.props.addTodo({ // <-- addTodo action injected into props
place:state.place,
title:state.title,
date:state.date,
description:state.description
});
setState({
title:"",
description:"",
place:"",
date:"",
});
}
return (
<div className="todoContainer">
...
</div>
)
};
const mapDispatchToProps = {
addTodo,
}
export default connect(null, mapDispatchToProps)(AddTodo); // <-- mapStateToProps is null
在Todos
組件中,您的 todos 狀態是一個數組,因此您可能希望將其映射到 JSX。 記住要解構傳遞的道具。 由於您沒有共享您的減速器或您如何組合減速器,我將假設只有一個用於位於狀態根的todos
減速器。
[更新] 由於您的rootReducer
似乎只是您的todos
reducer 函數,而且我沒有看到combineReducers
用於構建更復雜的狀態樹的位置,因此state
是您嘗試傳遞給Todos
組件的todos
數組狀態。 [/更新]
function Todos({ todos }) {
return (
<div className="todoDetail">
{todos.map((todo) => (
<h4 key={todo.id}>{todo.title}</h4>
))}
</div>
)
};
function mapStateToProps(state) {
return {
todos: state, // <-- state is todos array
};
}
export default connect(mapStateToProps)(Todos);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.