关于使用redux和reactjs的特定用户的点击查看详细信息

时间:2018-11-02 08:41:00

标签: javascript reactjs redux

因此,我正在使用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;

The ui for the same is here

我在左侧有一个聊天列表组件,在页面右侧有一个预览消息的组件。单击左侧时,我想查看详细信息。

1 个答案:

答案 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。

无论如何,我强烈建议您重组应用程序以使其更易于维护和可读。