简体   繁体   English

如何将 Props() 值传递给 setState() 以使用 ReactJs 使模态形式可编辑

[英]How to pass Props() value into setState() to make modal form editable using ReactJs

I am creating my blog where an user can able to edit his/her blogs.我正在创建我的bloguser可以在其中edit他/她的博客。 Here I am popping the data into a modal to make this edit ..在这里,我将数据弹出到模态中以进行此edit ..

So after all debugging and a better thinking I have figure this out.所以在调试和更好的思考之后我已经弄清楚了。 This is my updated working code for modal这是我更新的modal工作代码

Thank you for your time.感谢您的时间。

//blog.js //博客.js

class Blogs extends Component{
    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
    }

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

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

    replaceModalItem(id, blog_short_desc, blog_name , blog_desc, blog_image_link, blog_by, blog_by_author) {
        this.setState({
          modal: true,
          requiredItem: id,
          _id: id,
          blog_short_desc: blog_short_desc,
          blog_name: blog_name,
          blog_desc: blog_desc,
          blog_image_link: blog_image_link,
          blog_by: blog_by,
          blog_by_author: blog_by_author
        });
    }

    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);
        alert("Blog updated successfully!");
        e.target.reset();
        this.toggle();
        window.location.reload();
    }

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

        });
    }

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

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

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

    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 */}
                    <BlogData blogs={blogs} user={this.props.auth} handleCloseDialog={this.handleCloseDialog}  {...this.state} toggle={this.toggle}/>

                    {/* edit card dialog */}
                    <EditBlog onTodoChange={this.onTodoChange}  {...this.state} toggle={this.toggle} onSubmit={this.onSubmit}/>

                    <Grid style={{padding: 0}}  className="blog-grid">
                        {activeBlogs.map((item, i) => (
                            <Cell key={item._id} data-id={item._id} className="blog-grid-cell">   
                                <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 className="block-data-details">
                                            <Button className="blog-read-me-button col-4" onClick={this.handleOpenDialog.bind(this, item._id)}>Read </Button> 

                                            { isAuthenticated === true && (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, item.blog_short_desc, item.blog_name, item.blog_desc, item.blog_image_link, item.blog_by, item.blog_by_author )}  title="Edit Blog">
                                                <i className="fa fa-pencil" aria-hidden="true"></i>
                                            </a>
                                            </span> : null }
                                        </p>
                                        <p style={{ 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);

//Edit.js //编辑.js

    const EditBlog = ({ toggle, onTodoChange, onSubmit, ...state}) => {

    return( 
        <span>
            <Modal 
                isOpen = {state.modal && state.requiredItem === state._id}
                toggle = {()=>this.toggle(state._id)}    
            >
                <ModalHeader toggle={toggle}  style={{fontWeight: "bold"}}>
                    Edit your blog {state.blog_name}
                </ModalHeader>
                <ModalBody>
                    <Form onSubmit={e => onSubmit(e, state._id )}>
                        <FormGroup>
                            <Label for="blogHeading">Blog Heading</Label>
                            <Input type="text" name="blog_short_desc" id="blogHeading" placeholder="Update one liner"
                            onChange={onTodoChange} defaultValue={state.blog_short_desc}/>
                            <Label for="blogName">Blog Name</Label>
                            <Input type="text" name="blog_name" id="blogName" placeholder="Update blog name"
                            onChange={onTodoChange} defaultValue={state.blog_name}/>
                            <Label for="desc1">Description </Label>
                            <Input type="textarea" name="blog_desc" id="desc1" placeholder="Update your blog"
                            onChange={onTodoChange} defaultValue={state.blog_desc}/>
                            <Label for="imageUrl">Image Url</Label>
                            <Input type="text" name="blog_image_link" id="imageUrl" placeholder="Update image url (Optional)"
                            onChange={onTodoChange} defaultValue={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);

//CurrentUI of working edit //工作edit的当前UI

在此处输入图像描述

First, the uneditable bug is caused by using "value" props for your input in modal inside of "defaultValue".首先,不可编辑的错误是由于在“defaultValue”内的模态中使用“value”道具输入造成的。 If you use value, you are always giving it the value of initial props.如果你使用价值,你总是给它初始道具的价值。 Use default value.使用默认值。 Using defaultValue makes it a controlled component.使用 defaultValue 使其成为受控组件。 Read more on Stackoverflow here .此处阅读有关 Stackoverflow 的更多信息。 Change that and see next issues if any.更改它并查看下一个问题(如果有)。

Second, ensure you avoid UNSAFE_componentWillReceiveProps() .其次,确保避免使用 UNSAFE_componentWillReceiveProps() Looking at your componentWillRecieveProps method, what is said in the documentation may be at play:查看您的 componentWillRecieveProps 方法,文档中所说的可能在起作用:

"Calling this.setState() generally doesn't trigger UNSAFE_componentWillReceiveProps()." “调用 this.setState() 通常不会触发 UNSAFE_componentWillReceiveProps()。”

Update:更新:

Remove the componentWillReceiveProps method.删除 componentWillReceiveProps 方法。 submit should work.提交应该工作。 And ensure user is authenticated.并确保用户已通过身份验证。

It looks to me like your onTodoChange function is setting state on the parent Blogs component, but that state doesn't make it back to the input values.在我看来,您的onTodoChange function 正在父Blogs组件上设置 state,但 state 不会返回输入值。 Instead, the parent passes a blogs prop into EditBlogs , and since onTodoChange never affects blogs , the input's value remains unchanged.相反,父级将blogs属性传递给EditBlogs ,并且由于onTodoChange从不影响blogs ,因此输入的value保持不变。

This means your inputs' onChange event values ( e.target.value ) never make it back to the inputs' value attribute, so the input doesn't actually change values.这意味着您输入的onChange事件值 ( e.target.value ) 永远不会返回输入的value属性,因此输入实际上不会更改值。

Since the blog_ values in state and onTodoChange are all local to the edit form, I recommend moving those down to that level.. Blogs doesn't need to know about that stuff, and it'll simplify things - onTodoChange will set event values into state , which will flow right back into the inputs as values.由于stateonTodoChange中的blog_值都是编辑表单的本地值,我建议将它们向下移动到那个级别。 Blogs不需要知道这些东西,它会简化事情 - onTodoChange会将事件值设置为state ,它将作为值流回输入。

Your blogs prop should only set the initial state .你的blogs道具应该只设置初始的state

When a user is editing their blog, take their blog information and create an object like this当一个用户在编辑他们的博客时,拿他们的博客信息并创建一个 object 像这样

userBlogData={
  blog_heading: 'users blog heading',
  blog_name: 'users blog name',
  description: 'users blog description',
  image_url: 'users blog image url',
}

Update the modal form based on these objects.根据这些对象更新模态形式。 For example:例如:

<input name="blog_heading" value={blog_heading} ... />

After the user have edited the object you can make an update request on your server and call the get function at the same time for updating the blogs.用户编辑完 object 后,您可以在您的服务器上发出更新请求,同时调用 get function 来更新博客。 You can keep the update function on the edit component.您可以在编辑组件上保留更新 function。 But the get function will be passed as a props.但是 get function 将作为道具传递。

Hope This Helps希望这可以帮助

This should give you the idea...........................这应该给你的想法......................................

    // Edit Component

    this.state = {
       blog_name:this.props.data.blog_name
    }
    onBlogUpdate = () => {
      let payload = this.state
      API CALL...
     }
    ...
     render(){
        return(
            <input value={this.state.blog_name} name='blog_name' onChange={...} ... />
        )
     }

I have figure it out with我已经弄明白了

  1. OnClick of edit button I passed all required data along with it. edit按钮的OnClick我传递了所有必需的数据。 So, my replaceModalItem() binds all data together in setState()所以,我的replaceModalItem()setState()中将所有数据绑定在一起

  2. In replaceModalItem i called those data and set it to setState() .replaceModalItem ,我调用了这些数据并将其设置为setState()

  3. In Edit.js I have called all the state values.Edit.js ,我调用了所有state值。

Hence getting all the required values in input field setting it with defaultValue因此在输入字段中获取所有必需的值并将其设置为defaultValue

在此处输入图像描述

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

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