因此,我正在使用React + Redux创建一个非常简单的应用程序的核心。左侧有一组人员列表,我希望能够列出这些人员的详细信息,然后在用户单击右侧的一个时列出。
The Chat List component
import React, { Component, Fragment } from 'react';
import { Media } from 'reactstrap';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import Snackbar from '@material-ui/core/Snackbar';
import { InputGroup, InputGroupAddon, Input } from 'reactstrap';
import update from 'react-addons-update';
import { Scrollbars } from 'react-custom-scrollbars';
import Avatar from '@material-ui/core/Avatar';
import { withRouter } from 'react-router-dom';
import {connect} from 'react-redux';
import {getTicketingList} from '../../../actions/TicketingActions';
// api
import api from 'Api';
// intl messages
import IntlMessages from 'Util/IntlMessages';
import {ticketData} from './data';
// rct section loader
import RctSectionLoader from 'Components/RctSectionLoader/RctSectionLoader';
class TicketList extends Component {
state = {
sectionReload: false,
newEmails: null,
openConfirmationAlert: false,
selectedDeletedEmail: null,
snackbar: false,
snackbarMessage: '',
replyTextBox: false,
selectedEmail: null,
viewEmailDialog: false,
addNewUserModal: false, // add new user form modal
}
componentDidMount = ()=>{
this.props.
// on delete email open confirmation
onDeleteEmail(email) {
this.setState({ openConfirmationAlert: true, selectedDeletedEmail: email });
}
// close confirmation dailog
handleCloseConfirmationAlert = () => {
this.setState({ openConfirmationAlert: false, viewEmailDialog: false });
}
// delete email if confirmation true
deleteEmail() {
this.setState({ openConfirmationAlert: false, sectionReload: true });
let emails = this.state.newEmails;
let deletedEmailIndex = emails.indexOf(this.state.selectedDeletedEmail);
emails.splice(deletedEmailIndex, 1);
let self = this;
setTimeout(() => {
self.setState({ sectionReload: false, newEmails: emails, snackbar: true, snackbarMessage: 'Ticket Deleted Successfully!' });
}, 1500);
}
// show reply text box
showReplyTextBox(email) {
let indexOfEmail = this.state.newEmails.indexOf(email);
this.setState({
newEmails: update(this.state.newEmails,
{
[indexOfEmail]: {
replyTextBox: { $set: true }
}
}
)
});
}
// reply email
replyEmail(email) {
let indexOfEmail = this.state.newEmails.indexOf(email);
this.setState({ sectionReload: true });
this.setState({
newEmails: update(this.state.newEmails,
{
[indexOfEmail]: {
replyTextBox: { $set: false }
}
}
)
});
let self = this;
setTimeout(() => {
self.setState({ sectionReload: false, snackbar: true, snackbarMessage: 'Reply Sent Successfully!' });
}, 1500);
}
/**
* On View Email
*/
onViewEmal(email) {
this.setState({ selectedEmail: email, viewEmailDialog: true });
}
render() {
const { newEmails, selectedEmail, sectionReload } = this.state;
const {tickets} = this.props
console.log(tickets)
return (
<Fragment>
{sectionReload &&
<RctSectionLoader />
}
<Scrollbars className="rct-scroll" autoHeight autoHeightMin={100} autoHeightMax={400} autoHide>
<ul className="new-mail mb-0 list-unstyled">
{tickets.ticketData && tickets.ticketData.map((email, key) => (
<li key={key}>
<div className="d-flex justify-content-between">
<Media className="mb-10">
{email.userdate.sender_avatar === '' ?
<Avatar className="mr-15">{email.userdate.sender_name.charAt(0)}</Avatar>
: <Media object src={email.userdate.sender_avatar} alt="profile pic" className="rounded-circle mr-15" width="40" height="40" />
}
<span className="ticketnumber">#{email.ticket_num}</span>
<span className="ticketnumber">{email.userdate.sender_name}</span>
</Media>
<span className="small align-self-center">{email.userdate.date_created}</span>
</div>
<div className="d-flex justify-content-between">
<div className="text-justify">
<p className="subject">{email.userdate.subject}</p>
<p className="message">{email.userdate.message}</p>
{email.replyTextBox &&
<div className="task-foot d-flex justify-content-between">
<InputGroup>
<Input />
<InputGroupAddon addonType="append">
<Button variant="raised" color="primary" className="text-white" onClick={() => this.replyEmail(email)}>
<IntlMessages id="button.reply" />
</Button>
</InputGroupAddon>
</InputGroup>
</div>
}
</div>
<div className="hover-action text-right w-25 align-self">
{/* <Button color="primary" className="text-white mr-5 mb-5" variant="fab" mini onClick={() => this.onViewEmal(email)}><i className="zmdi zmdi-eye"></i></Button> */}
<Button className="btn-danger text-white mr-5 mb-5" variant="fab" mini onClick={() => this.onDeleteEmail(email)}><i className="zmdi zmdi-delete"></i></Button>
{/* <Button className="btn-success text-white mr-5 mb-5" variant="fab" mini onClick={() => this.showReplyTextBox(email)}><i className="zmdi zmdi-mail-reply"></i></Button> */}
</div>
</div>
</li>
))}
</ul>
</Scrollbars>
<Dialog
open={this.state.openConfirmationAlert}
onClose={this.handleCloseConfirmationAlert}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{"Are You Sure Want To Delete?"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
This will delete the email permanently from your emails.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button variant="raised" className="btn-danger text-white" onClick={this.handleCloseConfirmationAlert}>
<IntlMessages id="button.cancel" />
</Button>
<Button variant="raised" color="primary" className="text-white" onClick={() => this.deleteEmail()}>
<IntlMessages id="button.delete" />
</Button>
</DialogActions>
</Dialog>
<Dialog
open={this.state.viewEmailDialog}
onClose={this.handleCloseConfirmationAlert}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogContent>
{selectedEmail !== null &&
<div>
<div className="d-flex justify-content-between">
<Media className="mb-10">
{selectedEmail.sender_avatar === '' ?
<Avatar className="mr-15">{selectedEmail.sender_name.charAt(0)}</Avatar>
: <Media object src={selectedEmail.sender_avatar} alt="User Profile 1" className="rounded-circle mr-15" width="40" height="40" />
}
<Media body>
<h5 className="m-0 pt-5 fs-14">{selectedEmail.sender_name}</h5>
<span className="fs-12 align-self-center">{selectedEmail.from}</span>
</Media>
</Media>
<span className="small align-self-center">19 Mar 2017</span>
</div>
<div className="d-flex justify-content-between">
<div className="text-justify">
<p className="subject">{selectedEmail.subject}</p>
<p className="message">{selectedEmail.message}</p>
</div>
</div>
</div>
}
</DialogContent>
</Dialog>
<Snackbar
anchorOrigin={{
vertical: 'top',
horizontal: 'center',
}}
open={this.state.snackbar}
onClose={() => this.setState({ snackbar: false })}
autoHideDuration={2000}
snackbarcontentprops={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">{this.state.snackbarMessage}</span>}
/>
</Fragment>
);
}
}
const mapStateToProps = (store) => {
return {
tickets : store.tickets
}
};
export default connect(mapStateToProps, {getTicketingList})(TicketList);
The Right side component
import React, { Component } from 'react'
import './style.css';
import { Avatar } from '@material-ui/core';
import {connect} from 'react-redux';
import {ticketData} from './data';
import { Input} from 'reactstrap';
import {Button} from '@material-ui/core';
import {getTicketingList} from '../../../actions/TicketingActions';
// intl messages
import IntlMessages from 'Util/IntlMessages';
class Preview extends React.Component {
componentDidMount = ()=>{
this.props.getTicketingList()
}
render() {
const {tickets} = this.props
console.log(tickets)
return (
<div>
{tickets.ticketData.map((data, key) => (
<div className="lazy-up">
<div className="d-flex justify-content-inline headline">
<Avatar className="pre_avatar">{data.sender_avatar}</Avatar>
<span className="pre_span">#{data.ticket_num}</span>
</div>
<div className="card pt-30 mb-20 textspace">
<h3 className="text-pink d-block mb-5 headtxt">{data.subject}</h3>
<p className="fs-14 mb-10">{data.message}</p>
</div>
</div>
))}
</div>
);
}
}
const mapStateToProps = (store) => {
return {
tickets : store.tickets
}
};
export default connect(mapStateToProps, {getTicketingList})(Preview);
// action
import {
Ticketing_List
} from 'Actions/types';
import {ticketData} from '../routes/ticketing/ticket/data';
export const getTicketingList = () => {
return (dispatch) =>{
dispatch({
type: Ticketing_List,
payload: ticketData
});
}
}
export const onSelectUser = (user) => {
return {
type: ON_SELECT_USER,
payload: ticketData
};
};
import {
Ticketing_List
} from 'Actions/types';
import {ticketData} from '../routes/ticketing/ticket/data';
export const getTicketingList = () => {
return (dispatch) =>{
dispatch({
type: Ticketing_List,
payload: ticketData
});
}
}
//Reducer
import {
Ticketing_List,
ON_SELECT_USER,
} from 'Actions/types';
const INIT_STATE = {
ticketData:[]
};
export default (state = INIT_STATE, action) => {
switch (action.type) {
case Ticketing_List:
console.log("Ticketing_List")
return { ...state, ticketData: action.payload }
default: return { ...state };
}
}
我如何从列表中选择用户并使用Redux查看详细信息
index.js
import React, { Component } from 'react'
import './style.css';
import RctCollapsibleCard from 'Components/RctCollapsibleCard/RctCollapsibleCard';
import Preview from './preview';
import TicketList from './ticketList';
import { Button } from '@material-ui/core';
import {
Modal,
ModalHeader,
ModalBody,
ModalFooter,
} from 'reactstrap';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import AddNewUserForm from './addNewUser';
class Ticket extends React.Component {
state = {
all: false,
users: null, // initial user data
selectedUser: null, // selected user to perform operations
loading: false, // loading activity
addNewUserModal: false, // add new user form modal
addNewUserDetail: {
id: '',
name: '',
avatar: '',
dateCreated: 'Just Now',
checked: false
},
openViewUserDialog: false, // view user dialog box
editUser: null,
allSelected: false,
selectedUsers: 0,
userclicked:true,
}
/**
* Open Add New User Modal
*/
opnAddNewUserModal() {
this.setState({ addNewUserModal: true });
}
/**
* On Change Add New User Details
*/
onChangeAddNewUserDetails(key, value) {
this.setState({
addNewUserDetail: {
...this.state.addNewUserDetail,
[key]: value
}
});
}
/**
* Add New User
*/
addNewUser() {
const { name, emailAddress } = this.state.addNewUserDetail;
if (name !== '' && emailAddress !== '') {
let users = this.state.users;
let newUser = {
...this.state.addNewUserDetail,
id: new Date().getTime()
}
users.push(newUser);
this.setState({ addNewUserModal: false, loading: true });
let self = this;
setTimeout(() => {
self.setState({ loading: false, users });
NotificationManager.success('User Created!');
}, 2000);
}
}
/**
* On Add & Update User Modal Close
*/
onAddUpdateUserModalClose() {
this.setState({ addNewUserModal: false, editUser: null })
}
render() {
const { users, loading, selectedUser, editUser, allSelected, selectedUsers } = this.state;
return (
<div className="col-sm-12 col-md-12 col-lg-12 w-xs-full">
<div className="row">
<TicketList />
</div>
<div className="col-sm-9 col-md-7 col-lg-8 preview_block">
<Preview />
</div>
</div>
);
}
}
export default Ticket;
我在左侧有一个聊天列表组件,在页面右侧有一个预览消息的组件。单击左侧时,我想查看详细信息。
答案 0 :(得分:0)
在这种情况下,我会这样做:
1)创建一个动作chooseTicket
,然后在按列表项时触发该方法。见下文:
// TicketList component
<li key={key} onClick={ () => this.props.chooseTicket(email.id) }>
...
</li>
2)在简化器中添加一个名为chosenTicket
的新状态变量,并使用从操作传递到简化器的email.id
从数据数组中过滤出正确的项来填充该变量。 / p>
3)在chosenTicket
组件中引入Preview
,请参见以下示例:
// Preview component
...
render() {
const { chosenTicket } = this.props;
return (
// Use the ticket data and visualize the preview
);
}
...
话虽如此,我不建议您像这样构造代码。有更好的方法可以做到这一点。例如,将组件分成单独的文件。
我还认为在填充详细信息视图时从API提取正确的票证将是有益的。如果希望共享每个票证,则可以使用每个票证的URL。
无论如何,我强烈建议您重组应用程序以使其更易于维护和可读。