我正在尝试使用react、redux、redux表单和firestore数据库来构建todoList,我也可以使用动作或动作创建者将todo插入数据库中,我可以获取数据库中的数据存储,但当用户第一次访问网站时,我无法在网站上显示数据,此外,当用户添加todo并提交表单时,第一个todo项显示为空白!。有人能帮我告诉我的代码出了什么问题吗?
App.js
import React from 'react'
import { Container} from 'react-bootstrap'
import { connect } from 'react-redux'
import InputForm from './InputForm'
import Todo from './Todo'
import {listTodo} from '../actions'
class App extends React.Component {
constructor(props){
super(props);
this.renderList = this.renderList.bind(this);
}
componentDidMount(){
this.props.listTodo();
console.log(this.props.list);
}
renderList(){
return this.props.list.map((todo,id) => {
return (
<Todo todo={todo} key={id}/>
)
})
}
render() {
console.log("rendered");
if(!this.props.list){
return <div>Loading...</div>
}
return (
<Container fluid>
<h1 className="text-center" style={{marginTop: "5vh"}}>Todo App</h1>
<InputForm />
{this.renderList()}
</Container>
)
}
}
const mapStateToProps = (state) => {
console.log(state.todoList);
return {
list: state.todoList
}
}
export default connect(mapStateToProps, {listTodo})(App)
Todo.js
import React from 'react'
import { Card } from 'react-bootstrap'
class Todo extends React.Component {
render(){
console.log(this.props.todo);
return (
<Card className="text-center">
<Card.Body>
<Card.Text>{this.props.todo.todo}</Card.Text>
</Card.Body>
<Card.Footer className="text-muted">DeadLine by {this.props.todo.date}</Card.Footer>
</Card>
)
}
}
export default Todo
动作(索引.js(
import database from '../firebase/firebase'
export const addTodo = (inputValue) => {
database.collection('Todo').add({
todo: inputValue.todo_input,
date: inputValue.todo_date
});
return {
type: "ADD_TODO",
payload: inputValue
};
}
export const listTodo = () => {
const data = [];
database.collection('Todo').onSnapshot(snapshot => snapshot.docs.map(doc => data.push(doc.data())));
return {
type: 'LIST_TODO',
payload: data
}
}
export const deleteTodo = id => {
//delete todo
return {type: 'DELETE_TODO'}
}
TodoReducer.js
export default (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
case 'LIST_TODO':
return action.payload;
case 'DELETE_TODO':
return state.filter(item => item.id !== action.payload);
default:
return state;
}
}
reducers.js
import { combineReducers } from "redux";
import {reducer as formReducer} from 'redux-form'
import todoReducer from './TodoReducer'
export default combineReducers({
form: formReducer,
todoList: todoReducer
});
在listTodo
操作创建者中,创建一个对象data
,并将其作为LIST_TODO
操作的一部分返回。然后,此data
对象将持久化到您的存储中,然后由onSnapshot
回调操作,以便在之后将项目添加到该数据中。React Redux无法检测到这些更改,因此您的组件不会随内容自行更新。
export const listTodo = () => {
const data = [];
// do never do something like this!
database.collection('Todo').onSnapshot(snapshot => snapshot.docs.map(doc => data.push(doc.data())));
return {
type: 'LIST_TODO',
payload: data
}
}
这打破了第二个Redux原理";改变状态的唯一方法是发出一个动作,一个描述发生了什么的对象;。
要做到这一点,您需要使用中间件,最常见的是redux-thunk
中间件。
这已经包含在官方的Redux工具包中,我通常建议您查看。
既然向你展示如何正确地做到这一点会变成官方教程的1:1副本,那就去看看吧:
- 代表旧式"Vanilla Redux":Redux基础知识,第6部分:异步逻辑和数据获取
- 对于";现代Redux";使用Redux工具包:Redux Essentials,第5部分:异步逻辑和数据获取