我想订阅状态更改并在需要时重新渲染组件(状态更改) 呈现2个组件。我从中进行更新的一项(产品列表)和我从中显示所选项目的更新列表(产品购物车)
我无法从购物车中获取状态
这是购物车组件-我要在其中订阅商店c并在状态更改时重新呈现(不起作用)
import React, { Component } from 'react';
import Card from './Card'
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import store from '../lib/reducers/index'
const mapStateToProps = state => {
return { bookings: state.bookings };
};
class CartDetails extends Component {
constructor(props) {
super(props)
this.style = {
height: "50px",
margin: "5px 0",
borderRadius: "0"
}
// store.subscribe(() => {
// console.log(store.getState())
// this.setState({
// bookings: store.getState()
// });
// });
}
render() {
const bookings = this.props.bookings
return (<div className="side">
<ul className="list-group list-group-flush">
{bookings.map(booking => {
console.log("details " + booking.hotelDetails.bg)
return(<Card key={booking.id} bg={booking.hotelDetails.bg} style={this.style}>
<ul className="ml-auto mx-auto price text-right">
<li>€{booking.hotelDetails.price}</li>
<li>prix/nuit</li>
</ul>
</Card>)
})}
</ul>
<button className="btn btn-light float-right"><Link to="/order">Recap</Link></button>
</div>)
}
}
const Cart = connect(mapStateToProps)(CartDetails);
export default Cart;
这是HotelDetails组件-我在其中选择日期,夜晚以预订夜晚
import React, { Component } from 'react';
import bgImg from '../resources/1445991842772-097fea258e7b.jpeg'
import DatePicker from "react-datepicker";
import Card from './Card'
import "react-datepicker/dist/react-datepicker.css";
import { connect } from "react-redux";
import { addBooking } from "../lib/actions/index";
import PropTypes from 'prop-types'
function mapDispatchToProps(dispatch) {
return {
addBooking: payload => dispatch(addBooking(payload))
};
}
class FormReservation extends Component {
constructor(props) {
super(props)
this.state = {
hotelDetails: {},
nights: 1,
rooms: 0,
startDate: new Date(),
endDate: new Date(),
price: 0,
details: ""
}
this.hotels = [
{ bg: '1445991842772-097fea258e7b', price: 400 },
{ bg: '1496417263034-38ec4f0b665a', price: 300 },
{ bg: '1444201983204-c43cbd584d93', price: 450 },
{ bg: '1486591038957-19e7c73bdc41', price: 280 },
{ bg: '1515362655824-9a74989f318e', price: 320 },
{ bg: '1518733057094-95b53143d2a7', price: 550 },
{ bg: '1519449556851-5720b33024e7', price: 400 },
{ bg: '1525905708812-b271b5e3b2f3', price: 180 },
{ bg: '1495754149474-e54c07932677', price: 300 },
{ bg: '1561578428-b13076fe7ea0', price: 200 },
{ bg: '1566399468396-07a2a14911a6', price: 400 },
{ bg: '1544305776-64b90477a4da', price: 500 },
{ bg: '1487757619811-5dad58c96a7a', price: 400 },
{ bg: '1421790735934-58176b8292a7', price: 600 },
{ bg: '1551043415-844a4ab9f4fa', price: 450 }
]
this.style = {
height: "150px",
margin: "10px",
borderRadius: "0"
}
}
componentDidMount() {
this.setCheckout()
const id = this.props.match.params.id
let hotel = this.hotels.filter(hotel => {
return hotel.bg == id
})
console.log('hotel ' + hotel)
this.setState({ hotelDetails: hotel })
}
setCheckout = () => {
let day = this.state.startDate.getDate() + parseInt(this.state.nights)
let month = this.state.startDate.getMonth() + 1
let year = this.state.startDate.getFullYear()
this.setState({
endDate: new Date(month + "/" + day + "/" + year)
})
}
setNights = () => {
const second = 1000, minute = second * 60, hour = minute * 60, day = hour * 24
const distance = Math.floor((this.state.endDate.getTime() - this.state.startDate.getTime()) / day)
this.setState({ nights: distance })
}
onAdd = e => {
e.preventDefault()
const { startDate, endDate, nights, rooms, hotelDetails } = this.state;
if (nights == 0 || rooms == 0) { return false }
let id = new Date().getTime();
this.props.addBooking({ id, startDate, endDate, nights, rooms, hotelDetails });
}
onNightsSelect = e => {
this.setState({ nights: e.target.value }, () => {
this.setCheckout()
})
}
onRoomSelect = e => {
this.setState({ rooms: e.target.value })
}
handleCheckIn = e => {
this.setState({ startDate: e }, () => { this.setCheckout() })
}
handleCheckOut = e => {
this.setState({ endDate: e }, () => { this.setNights() })
}
render() {
const id = this.props.match.params.id
return (
<div>
<Card bg={id} style={this.style}></Card>
<div id="hotelDetails">
<div className="bgImg"
style={{
backgroundImage: `url('${bgImg}')`,
backgroundSize: 'cover'
}}></div>
<br /> <br />
<div className="container">
<div className="row">
<div className="col-md-6">
<DatePicker
className="form-control datepicker"
selected={this.state.startDate}
onChange={(e) => this.handleCheckIn(e)}
dateFormat="EEEE, MMM d, yyyy" />
</div>
<div className="col-md-6">
<DatePicker
className="form-control datepicker"
selected={this.state.endDate}
onChange={(e) => this.handleCheckOut(e)}
dateFormat="EEEE, MMM d, yyyy" />
</div>
</div>
<br /> <br />
<form class="form" onSubmit={(e) => this.onAdd(e)}>
<div className="row">
<div className="col-md-6">
<div class="form-group">
<label for="exampleFormControlSelect1">Nights</label>
<br />
<select class="form-control" id="exampleFormControlSelect1"
onChange={(e) => this.onNightsSelect(e)}
value={this.state.nights}
>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</div>
<div className="col-md-6">
<div class="form-group">
<label for="exampleFormControlSelect1">Rooms</label>
<br />
<select class="form-control" id="exampleFormControlSelect1"
value={this.state.rooms}
onChange={(e) => this.onRoomSelect(e)}>
<option>-</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</div>
</div>
<div className="row">
<div className="col-md-12 text-right">
<p>{this.state.rooms} Rooms, {this.state.nights} Nights</p>
</div>
</div>
<br /> <br />
<div className="row">
<div className="col-md-6 offset-6">
<button type="submit" class="btn btn-success float-right">Add + </button>
</div>
</div>
</form>
</div>
</div>
</div>
)
}
}
const HotelDetails = connect(null, mapDispatchToProps)(FormReservation);
export default HotelDetails;
HotelDetails.propTypes = {
rooms: PropTypes.number.isRequired,
nights: PropTypes.number.isRequired,
price: PropTypes.number.isRequired
}
商店
import { createStore } from "redux";
import rootReducer from "../reducers/index";
const store = createStore(rootReducer);
export default store;
操作
/*
* constants
*/
export const ADD_BOOKING = "ADD_BOOKING";
export const CONFIRM_ORDER = "CONFIRM_ORDER";
export const ADD_ORDER = "ADD_ORDER";
/*
* action creators
*/
export const addBooking = payload => ({
type: ADD_BOOKING,
payload: payload
});
export const addOrder = payload => ({
type: ADD_ORDER,
payload: payload
});
export const confirmOrder = payload => ({
type: CONFIRM_ORDER,
payload: payload
});
减速器
const initialState = {
bookings: [],
order: {}
};
function rootReducer(state = initialState, action) {
if (action.type === ADD_BOOKING) {
return Object.assign({}, state, {
bookings: state.bookings.concat(action.payload)
});
}
if (action.type === ADD_ORDER) {
return Object.assign({}, state, {
order: action.payload
})
}
return state;
}
export default rootReducer;
这是该站点的演示