我将在这里发布我的问题,希望能学到一些东西!我一直在学习一个教程,但还没有深入了解React和Redux,无法有效地了解发生了什么。我想在React和Redux中创建将业务添加和删除到全局状态的功能。根据我在谷歌上搜索的内容,我知道文件结构因项目而异,所以我会在这里发布所有文件。我把它们分为actions.js、reducers.js、state.js和store.js。这是我的文件:
redux/actions.js:
export const addListing = (newBusiness) => {
return {
type: 'ADD_LISTING',
value: newBusiness
}
}
export const removeListing = (index) => {
return {
type: 'REMOVE_LISTING',
value: index
}
}
redux/reducers.js:
import { combineReducers } from 'redux';
import { addBusiness, removeBusiness } from './actions'
const user = (state = null) => state
// add switch statements in here
const businesses = (state = [], action) => {
switch(action.type) {
case 'ADD_BUSINESS':
return [ ...state, action.value ]
case 'REMOVE_BUSINESS':
const newState = [ ...state ]
newState.splice(action.value, 1);
return newState;
default: // need this for default case
return state
}
}
export default combineReducers({ user, businesses })
redux/state.js
export default {
user: {
username: 'test-user-1',
email: 'test-user@example.com'
},
businesses: [
{
"id": 15,
"name": "My pizza",
"description":"Homemade pizza shop",
"address": "123 Taco Street",
"hours": "9-5"
}
]
};
redux/store.js
import { createStore } from 'redux'
import reducers from './reducers'
import state from './state'
export default createStore(reducers, state)
containers/addListing.js
import { connect } from "react-redux";
import { addListing } from '../redux/actions';
import AddListing from '../components/addListing'
const mapDispatchToProps = (dispatch) => {
return {
addListing: (business) => dispatch(addListing(business)),
}
}
export default connect(null, mapDispatchToProps)(AddListing)
容器/removeListing.js
import { connect } from "react-redux";
import { removeListing } from '../redux/actions';
const mapDispatchToProps = (dispatch) => {
return {
removeCar: (business) => dispatch(removeListing(business)),
}
}
export default connect(null, mapDispatchToProps)(removeListing)
containers/Listing.js:
import { connect } from 'react-redux'
import Listing from '../components/Listing'
const mapStateToProps = (state) => {
return {
businesses: state.businesses,
user: state.user.username
}
}
export default connect(mapStateToProps)(Listing)
components/addListing.js
import React from 'react';
import { InputLabel } from '@material-ui/core'
import { Input } from '@material-ui/core'
import { FormControl } from '@material-ui/core';
import { Button } from '@material-ui/core';
import { TextField } from '@material-ui/core';
import '../redux/state';
class addListing extends React.Component {
state = {
name: '',
description: '',
address: '',
hours: ''
}
handleTextChange = (e) => {
const newState = { ...this.state }
newState[e.target.id] = e.target.value
this.setState(newState)
console.log(this.state)
}
handleSubmit = (e) => {
e.preventDefault()
const payload = { ...this.state }
console.log("THE BUSINESS", payload)
this.props.addListing(payload)
console.log(this.props)
}
componentDidUpdate = (prevProps, prevState) => {
if (prevState.open !== this.state.open) {
this.setState({
name: '',
description: '',
address: '',
hours: ''
})
}
}
render(){
return (
<div className="App">
<form
onSubmit={this.handleSubmit}
style={{ display: 'flex', flexDirection: 'column', width: '350px' }}>
<TextField
id="name"
name="name"
placeholder="Name"
value={this.state.name}
onChange={this.handleTextChange}
required />
<TextField
id="description"
name="description"
placeholder="Description"
value={this.state.description}
onChange={this.handleTextChange}
required />
<TextField
id="address"
name="address"
placeholder="Address"
value={this.state.address}
onChange={this.handleTextChange}
required />
<TextField
id="hours"
name="hours"
placeholder="Hours"
value={this.state.hours}
onChange={this.handleTextChange}
required />
<br />
<Button variant="contained" color="primary" type="submit">Submit</Button>
</form>
</div>
);
}
}
export default addListing;
components/Listing.js:
import React from 'react'
import {
Container,
Table,
TableBody,
TableCell,
TableHead,
TableRow
} from '@material-ui/core'
import DeleteIcon from '@material-ui/icons/Delete'
import addListing from '../containers/addListing'
import removeListing from '../containers/removeListing'
import businesses from '../redux/state'
import user from '../redux/state';
const Listing = (props) => {
console.log(props.businesses)
return (
<Container maxWidth="lg" className="car-container">
<h4>Welcome, {props.user.username}</h4>
<div className="flex-container">
</div>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell>Description</TableCell>
<TableCell>Address</TableCell>
<TableCell>Hours</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.businesses.map((businesses, idx) => (
<TableRow key={businesses.id}>
<TableCell component="th" scope="row">
</TableCell>
<TableCell>{businesses["name"]}</TableCell>
<TableCell>{businesses["description"]}</TableCell>
<TableCell>{businesses["address"]}</TableCell>
<TableCell>{businesses["hours"]}</TableCell>
<TableCell>
<DeleteIcon
// add onClick method here
// onClick={props.removeCar(idx)}
className="icon text-red"
onClick={ () => this.props.removeListing(idx)}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Container>
)
}
export default Listing
App.js:
import React from 'react';
import Navigation from './components/Navigation'
import './App.css'
import Router from './Router'
import { BrowserRouter } from 'react-router-dom'
import { Provider } from 'react-redux'
import store from './redux/store'
function App() {
return (
<Provider store={store}>
<BrowserRouter>
<Navigation />
<Router />
</BrowserRouter>
</Provider>
);
}
export default App;
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Login from './components/Login'
import App from './App';
import * as serviceWorker from './serviceWorker';
import Listing from '../src/components/Listing';
import { Provider } from 'react-redux';
ReactDOM.render(
<App />,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
到目前为止,我知道这很简单。我没有收到任何错误,但它似乎并没有将新的列表添加到全局状态。当我进入列表视图时,它只显示我在state.js中默认包含的业务。我会尝试快速回复,如果需要更多信息,请告诉我。谢谢
我看到您的操作的名称是不同的ADD_LISTING
与ADD_BUSINESS
,REMOVE_LISTING
与REMOVE_BUSINESS
。
在addListing
中有{type: 'ADD_LISTING', ...}
,在减速器中有case 'ADD_BUSINESS':
。字符串是不同的。他们需要匹配。尝试重命名ADD_BUSINESS
=>ADD_LISTING
和REMOVE_BUSINESS
=>REMOVE_LISTING
。
关于50号线的撞车事故。您不需要this.
,因为您的组件不是class
类型。将其更改为onClick={ () => props.removeListing(idx)}
。
mapDispatchToProps
中缺少removeListing
。
此外,用于Chrome的Redux DevTools插件可以帮助您调试Redux的问题。。