[英]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.