简体   繁体   English

如何使用 ReactJs 中的键从父级打开子组件模态

[英]How to open child component modal from parent by using its key in ReactJs

I am creating my blog where I want to edit the each blog respectively on click of it edit button.我正在创建我的博客,我想在单击编辑按钮时分别编辑每个博客。 Now modal is opening for respective id but value is not set with state value.现在模式正在为各自的 id 打开,但值未设置为state值。 That is componentwillmount is not properly working.那就是componentwillmount不能正常工作。

Any suggestion what i made mistake here?任何建议我在这里犯了什么错误? It will be helpful.这会很有帮助。 How can I make this possible witht he current set of code.如何使用当前的代码集实现这一点。

//blog.js (Parent component) //blog.js(父组件)

import React, {Component} from 'react';
import ReactGA from 'react-ga';
import {Card, Grid, Cell, Dialog, CardMenu, Button, CardTitle, CardText, CardActions, FABButton, Icon} from'react-mdl';
import { Container, Modal,  ModalHeader, ModalBody, Form, FormGroup, Label, Input,} from 'reactstrap';
import { connect } from 'react-redux';
import { getBlog, deleteBlog, updateBlog } from '../../actions/resumeActions';
import PropTypes from 'prop-types';
import Loading from './Loading';
import Moment from 'moment';
import BlogModal from "./BlogModal";
import Pagination from "react-js-pagination";
// import EditBlog from "./EditBlog";

class Blogs extends Component{
    initializeReactGA() {
        ReactGA.initialize('UA-132348738-1');
        ReactGA.pageview('/contact');
    }
    constructor(props) {
        super(props);
            this.state = {
                modal: false,
                justClicked: null,
                activePage: 1,
                requiredItem : null,
                _id: '',
                blog_short_desc: '',
                blog_name: '',
                blog_desc: '',
                blog_image_link: '',
                blog_by: '',
                blog_by_author: ''
            };
            this.handleOpenDialog = this.handleOpenDialog.bind(this);
              this.handleCloseDialog = this.handleCloseDialog.bind(this);
              this.replaceModalItem = this.replaceModalItem.bind(this);
            this.onTodoChange = this.onTodoChange.bind(this);
        }

    static propTypes = {
        getBlog: PropTypes.func.isRequired,
        deleteBlog: PropTypes.func.isRequired,
        updateBlog: PropTypes.func.isRequired,
        resume: PropTypes.object.isRequired,
        auth: PropTypes.object.isRequired,
        loading: PropTypes.object.isRequired
    }

    UNSAFE_componentWillReceiveProps(nextProps) {
        this.setState({
            value: nextProps.name
        })
    }

    toggle = (id) => {
        this.setState({
            modal: !this.state.modal
        });
    }

    componentWillMount() {
debugger
        this.props.resume["blogs"].map((blog) => {
            this.setState({
                updatable : false,
                _id: blog._id,
                blog_short_desc: blog.blog_short_desc,
                blog_name: blog.blog_name,
                blog_desc: blog.blog_desc,
                blog_image_link: blog.blog_image_link,
                blog_by: blog.blog_by,
                blog_by_author: blog.blog_by_author
            });
        })
    }

    replaceModalItem(id) {
        debugger
        this.setState({
          modal: true,
          requiredItem: id

        });
        debugger
    }

    onTodoChange = (e) => {
        this.setState({ 
            [e.target.name] : e.target.value 
        });
    }

    onSubmit = (e, id) => {
        e.preventDefault();
        const updatedBlog = {
            blog_short_desc: this.state.blog_short_desc,
            blog_name: this.state.blog_name,
            blog_desc: this.state.blog_desc,
            blog_image_link: this.state.blog_image_link,
            blog_by:  this.props.auth["user"]._id,
            blog_by_author: this.props.auth["user"].name
        }
        //update blog via updateblog action
        this.props.updateBlog(id, updatedBlog, this.props.history);
        alert("Blog updated successfully!");
        //close modal
        e.target.reset();
        this.toggle();
    }

    handleOpenDialog(id) {
        this.setState({
          openDialog: true,
          OpenEditDialog: true,
          justClicked: id

        });
    }

    handleCloseDialog() {
    this.setState({
        openDialog: false
    });
    }

    componentDidMount() {
        this.props.getBlog();
    }

    onDeleteBlogClick = (id) => {
        this.props.deleteBlog(id);
    };

    handlePageChange(pageNumber) {
        this.setState({activePage: pageNumber});
    }

    cardDialog(blogs, user){
        const itemsPerPage = 6; 
        let activeBlogs = blogs.slice (itemsPerPage * this.state.activePage - itemsPerPage, itemsPerPage * this.state.activePage);
        return( 
            <Grid style={{padding: 0, display: 'contents'}}>

                {activeBlogs.map(({ _id, blog_name, blog_desc, blog_image_link, blog_by_author }) => (
                <Cell col={12}>
                    <Dialog open={this.state.openDialog && this.state.justClicked === _id} className="open-dialog">

                        {blog_image_link ?
                            (<CardTitle style={{color: '#fff', height: '176px', backgroundImage: `url(${blog_image_link})`, backgroundPosition: 'center',
                            backgroundSize: 'cover',
                            backgroundRepeat: 'no-repeat'}}>{blog_name}</CardTitle>) :

                            (<CardTitle className="card-blog-title-image">{blog_name}</CardTitle>
                            )
                        }
                        <CardText>
                            {blog_desc}
                        </CardText>
                        <CardActions border>
                        <p style={{float:'right', fontWeight:'bold'}}>Author: {blog_by_author}</p>
                        </CardActions>
                        <CardMenu style={{color: '#fff'}}>
                            <FABButton onClick={this.handleCloseDialog} className="close-button" >
                                <Icon name="close" />
                            </FABButton>
                        </CardMenu>
                    </Dialog>
                </Cell>
                ))}
            </Grid>
        )
    }

    editcardDialog(blogs, user){
        const itemsPerPage = 6; 
        let activeBlogs = blogs.slice (itemsPerPage * this.state.activePage - itemsPerPage, itemsPerPage * this.state.activePage);
        return( 
            <span>
                <a className="btn edit-btn-blog-post" href="#" onClick={this.toggle}  title="Edit Blog">
                    <i className="fa fa-pencil" aria-hidden="true"></i>
                </a>
                {activeBlogs.map(({ _id, blog_short_desc, blog_name, blog_desc, blog_image_link, blog_by_author }) => (
                <Modal 
                    isOpen = {this.state.modal && this.state.requiredItem === _id}
                    toggle = {()=>this.toggle(_id)}    
                >
                    <ModalHeader toggle={this.toggle}  style={{fontWeight: "bold"}}>
                        Edit your blog {this.state.blog_name}
                    </ModalHeader>
                    <ModalBody>
                        <Form onSubmit={e => this.onSubmit(e, this.state._id )}>
                            <FormGroup>
                                <Label for="blogHeading">Blog Heading</Label>
                                <Input type="text" name="blog_short_desc" id="blogHeading" placeholder="Update one liner"
                                onChange={this.onTodoChange} value={blog_short_desc}/>
                                 <Label for="blogName">Blog Name</Label>
                                <Input type="text" name="blog_name" id="blogName" placeholder="Update blog name"
                                onChange={this.onTodoChange} value={blog_name}/>
                                <Label for="desc1">Description </Label>
                                <Input type="textarea" name="blog_desc" id="desc1" placeholder="Update your blog"
                                onChange={this.onTodoChange} value={blog_desc}/>
                                 <Label for="imageUrl">Image Url</Label>
                                <Input type="text" name="blog_image_link" id="imageUrl" placeholder="Update image url (Optional)"
                                onChange={this.onTodoChange} value={blog_image_link}/>
                                <Button
                                    color="dark"
                                    style={{marginTop: '2rem'}}
                                    block
                                >Edit blog</Button>
                            </FormGroup>
                        </Form>
                    </ModalBody>
                </Modal>
                ))}
            </span>
        )
    }

    render(){
        const { blogs, loading} = this.props.resume;
        const {  user, isAuthenticated } = this.props.auth;
        const itemsPerPage = 6; 
        let activeBlogs = blogs.slice (itemsPerPage * this.state.activePage - itemsPerPage, itemsPerPage * this.state.activePage);
        return(
            <Container>

            {loading ? (
            <div><Loading/></div>
            ) : (
                <div>
                    {/* blog modal */}
                    <BlogModal />

                    {/* card dialog */}
                    {this.cardDialog(blogs, user)}

                    {this.editcardDialog(blogs, user)}

                    <Grid style={{padding: 0}} id="todo">
                        {activeBlogs.map((item, i) => (
                            <Cell key={item._id} data-id={item._id}>   
                                <Card shadow={5} className="cards-grid">


                                    {item.blog_image_link ?
                                        (<CardTitle style={{color: '#fff', height: '200px',
                                        width: 'auto', backgroundImage: `url(${item.blog_image_link})`, backgroundPosition: 'center',
                                        backgroundSize: 'cover',
                                        backgroundRepeat: 'no-repeat'}}></CardTitle>) :

                                        (<CardTitle className="card-title-image"></CardTitle>
                                        )
                                    }

                                    <CardText>
                                        <b>{item.blog_short_desc}</b>
                                    </CardText>

                                    <CardActions border>
                                        <p>
                                        <Button className="blog-read-me-button col-4" onClick={this.handleOpenDialog.bind(this, item._id)}>Read </Button> 

                                        { isAuthenticated && (item.blog_by === user._id) ? 
                                        <span className="col=8">

                                        <Button className="remove-btn-blog-post"
                                        color="danger"
                                        size="sm"
                                        onClick= {this.onDeleteBlogClick.bind(this, item._id)} title="Delete Blog">
                                            &times;
                                        </Button> 
                                        <a className="btn edit-btn-blog-post" href="#" onClick={this.replaceModalItem.bind(this, item._id)}  title="Edit Blog">
                                            <i className="fa fa-pencil" aria-hidden="true"></i>
                                        </a> 

                                        {/* <a className="btn edit-btn-blog-post" href="#" onClick={this.handleEditOpenDialog.bind(this, item._id)}  title="Edit Blog">
                                            <i className="fa fa-pencil" aria-hidden="true"></i>
                                        </a> */}

                                        </span> : null }
                                        </p>

                                        <p style={{ fontStyle:'italic', fontWeight:'bold'}}>By-{item.blog_by_author} <span style={{float:'right',}}>{Moment(item.date).format('Do MMMM YYYY')}</span></p> 
                                    </CardActions>
                                </Card>  
                            </Cell>  
                        ))} 
                    </Grid>
                </div> 
                )}
                <Pagination
                    activePage={this.state.activePage}
                    itemsCountPerPage={6}
                    totalItemsCount={blogs.length}
                    pageRangeDisplayed={5}
                    onChange={this.handlePageChange.bind(this)}
                    itemClass='page-item'
                    linkClass='page-link'
                />
            </Container>
        ) 
   }
}

const mapStateToProps = (state) => ({
    resume: state.resume,
    auth: state.auth,
    loading: state.apiCallsInProgress > 0
});

export default connect(mapStateToProps, {getBlog, deleteBlog, updateBlog }) (Blogs);

Why don't you handle all your posts with your parent component, and use the <EditBlog / only as a functinal component.为什么不使用父组件处理所有帖子,并将<EditBlog /仅用作功能组件。 Here is a example and the correponding fiddle:这是一个示例和相应的小提琴:

const EditBlog = ({title, content, handleEdit}) => {
return (
                <div classname="editblog">
          <h1>{title}</h1>
          <p>{content}</p>
          <button onClick={handleEdit}>Edit</button>
        </div>
        )
}

class Blog extends React.Component {
constructor(props) {
super(props);
this.state= {
activeBlogs: [
{title: "Heading 1", content: "Content 1"},
{title: "Heading 2", content: "Content 2"}
],
editId: -1,
}
this.handleEdit = this.handleEdit.bind(this);
}

handleEdit(e) {
const {editId, activeBlogs} = this.state;
let newActiveBlogs = [...activeBlogs];
const {name, value } = e.target;
newActiveBlogs[editId]= Object.assign(newActiveBlogs[editId], {[name]: value});
if(editId >= 0) {
this.setState({
activeBlogs: newActiveBlogs
})
}

}
  render() {
  const {activeBlogs, editId} = this.state;
    return (
    <div classname="blog">
    {activeBlogs.map((item, index) => {
        return <EditBlog key={index} {...item} handleEdit={()=>this.setState({editId: index})} />
    })} 
    {editId >= 0 && activeBlogs.length && 
    <div classname="modal">
        <h2>Edit Modal is open</h2>
        <input name="title" value={activeBlogs[editId].title} onChange={this.handleEdit}></input>
        <input name="content" value={activeBlogs[editId].content} onChange={this.handleEdit}></input>
        <button onClick={()=>this.setState({editId:-1})}>Save</button>
    </div>
    }
    </div>
  )
}
}

ReactDOM.render(
  <Blog name="Blog" />,
  document.getElementById('container')
);

fiddle小提琴

Try the below one试试下面的

 class EditBlog extends Component {
        constructor(props) {
            super(props);
                this.state = {
                    modal: null,
                    requiredItem : null,
                    _id: '',
                    blog_short_desc: '',
                    blog_name: '',
                    blog_desc: '',
                    blog_image_link: '',
                    blog_by: '',
                    blog_by_author: ''
                };
                this.replaceModalItem = this.replaceModalItem.bind(this);
                this.onTodoChange = this.onTodoChange.bind(this);

            }

        static propTypes = {
            auth: PropTypes.object.isRequired,
            updateBlog: PropTypes.func.isRequired,
            editBlog: PropTypes.func.isRequired,
            resume: PropTypes.object.isRequired,
        }

        UNSAFE_componentWillReceiveProps(nextProps) {
            this.setState({
                value: nextProps.name
            })
        }
        toggle = (id) => {
            this.setState({
                modal: id
            });
        }
        componentWillMount() {

            this.props.resume["blogs"].map((blog) => {
                this.setState({
                    updatable : false,
                    _id: blog._id,
                    blog_short_desc: blog.blog_short_desc,
                    blog_name: blog.blog_name,
                    blog_desc: blog.blog_desc,
                    blog_image_link: blog.blog_image_link,
                    blog_by: blog.blog_by,
                    blog_by_author: blog.blog_by_author
                });
            })
        }

        replaceModalItem(id) {
            this.setState({
              openDialog: true,
              OpenEditDialog: true,
              requiredItem: id

            });
        }

        onTodoChange = (e) => {
            this.setState({ 
                [e.target.name] : e.target.value 
            });
        }

        onSubmit = (e, id) => {
            e.preventDefault();
            const updatedBlog = {
                blog_short_desc: this.state.blog_short_desc,
                blog_name: this.state.blog_name,
                blog_desc: this.state.blog_desc,
                blog_image_link: this.state.blog_image_link,
                blog_by:  this.props.auth["user"]._id,
                blog_by_author: this.props.auth["user"].name
            }
            //update blog via updateblog action
            this.props.updateBlog(id, updatedBlog, this.props.history);
            alert("Blog updated successfully!");
            //close modal
            e.target.reset();
            this.toggle();
        }
        render(){

            return(
                <span>
       <a className="btn edit-btn-blog-post" href="#" onClick={()=>this.toggle(this.state._id)} title="Edit Blog">
                    <i className="fa fa-pencil" aria-hidden="true"></i>
                </a>
                    <Modal 
                        isOpen = {this.state.modal===this.state._id}
                        toggle = {()=>this.toggle(this.state._id)}   
                    >
                        <ModalHeader toggle={()=>this.toggle(this.state._id)} style={{fontWeight: "bold"}}>
                            Edit your blog {this.state.blog_name}
                        </ModalHeader>
                        <ModalBody>
                            <Form onSubmit={e => this.onSubmit(e, this.state._id, )}>
                                <FormGroup>
                                    <Label for="blogHeading">Blog Heading</Label>
                                    <Input type="text" name="blog_short_desc" id="blogHeading" placeholder="Update one liner"
                                    onChange={this.onTodoChange} value={this.state.blog_short_desc}/>
                                     <Label for="blogName">Blog Name</Label>
                                    <Input type="text" name="blog_name" id="blogName" placeholder="Update blog name"
                                    onChange={this.onTodoChange} value={this.state.blog_name}/>
                                    <Label for="desc1">Description </Label>
                                    <Input type="textarea" name="blog_desc" id="desc1" placeholder="Update your blog"
                                    onChange={this.onTodoChange} value={this.state.blog_desc}/>
                                     <Label for="imageUrl">Image Url</Label>
                                    <Input type="text" name="blog_image_link" id="imageUrl" placeholder="Update image url (Optional)"
                                    onChange={this.onTodoChange} value={this.state.blog_image_link}/>
                                    <Button
                                        color="dark"
                                        style={{marginTop: '2rem'}}
                                        block
                                    >Edit blog</Button>
                                </FormGroup>
                            </Form>
                        </ModalBody>
                    </Modal>
                </span>
            )
        }
    }

    const mapStateToProps = state => ({
        resume: state.resume,
        auth: state.auth
    })

    export default connect(mapStateToProps, { updateBlog })(EditBlog);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM