简体   繁体   中英

Set props as state in child component

Here i want to set props to state in child component. I have a table that fill with ajax request. btw I'm using antd library. there is an Edit button on my table that should open a modal that contains a form.

Parent Component

  import React, {Component} from 'react';
import axios from 'axios';
import API from '../../Helpers/Api'
import {Table, Divider, Tag, message, Popconfirm, Icon} from 'antd';
import {
  Card,
  CardBody,
  CardHeader,
  Col,
  Row
} from 'reactstrap';
import EditCountry from './EditCountry'


var token = JSON.parse(localStorage.getItem("token"));
let config = {
  headers: {
    Authorization: token,
    Accept: 'application/json'
  }
}


class ListCountry extends Component {
  constructor(props) {
    super(props);
    this.columns = [
      {
        title: 'نام کشور‌',
        dataIndex: 'name',
        key: 'name',
        // render: text => <a href="javascript:;">{text}</a>,
      },
      {
        title: 'وضعیت',
        dataIndex: 'isForeign',
        key: 'isForeign',
        render: isForeign => (
          <div>
            <Tag color={isForeign ? 'blue' : 'purple'}>
              {isForeign ? 'کشور خارجی است' : 'کشور خارجی نیست'}
            </Tag>

          </div>
        ),
      },
      {
        title: '',
        dataIndex: '',
        key: 'x',
        render: (text, record) =>
          this.state.countries.length >= 1 ? (
            <span>
               <a onClick={() => this.handleEdit(record.key)}>ویرایش کشور</a>
               <Divider type="vertical" />
               <Popconfirm
                 icon={<Icon type="question-circle-o" style={{ color: 'red' }} />}
                 title="آیا از حذف این کشور مطمئن هستید؟"
                 onConfirm={() => this.handleDelete(record.key)}
                 okText="حذف"
                 cancelText="لغو"
               >
                 <a>حذف کشور</a>
              </Popconfirm>
            </span>

          ) : null,
      },
    ];
    this.state = {
      countries: [],
      openModal: false,
      rowId:''
    }
  }

  getCountries = e => {
    var self = this;
    axios.get( API + '/country',
      config
    )
      .then(function (response) {

        const results= response.data.map(row => ({
          key: row._id, // I added this line
          name: row.name,
          isForeign: row.isForeign,
          Id: row._id,
        }))
        self.setState({ countries : results });
      })
      .catch(function (error) {
        console.log(error);
      });
  };
  componentDidMount() {
      this.getCountries();
  }

  handleDelete = id => {
    var self = this;
    axios.delete( API + `/country/${id}`,
      config
    )
      .then(function (response) {
        const countries = [...self.state.countries];
        self.setState({ countries: countries.filter(item => item.key !== id) });
        message.success('عملیات حذف با موفقیت انجام شد.')
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  handleEdit = id => {
    this.setState({
      rowId: id,
      openModal: !this.state.openModal
    })
  }
  render() {
      return (
        <div className="animated fadeIn">
          <Row className="justify-content-center">
            <Col xs="12" md="12">
              <Card>
                <CardHeader>
                  <strong>لیست کشورها</strong>
                </CardHeader>
                <CardBody>
          <Table className="rtl text-right" columns={this.columns} dataSource={this.state.countries}/>
          <EditCountry open={ this.state.openModal } handleEdit= {this.handleEdit} rowId={ this.state.rowId } />
                </CardBody>
              </Card>
            </Col>
          </Row>
        </div>
      )
  }
}

export default ListCountry;

Child Component

    class EditCountry extends Component {

      constructor(props) {
        super(props);
        this.state = {
          id : this.props.rowId
        };
      }

      handleCancel = () => {
          this.props.handleEdit();
      };
      render() {
        return (
          <div>
            <Modal
              title="Basic Modal"
            >
// form
            </Modal>
          </div>
        );
      }
    }

so as you see i'm setting props as state but the id is empty, am i missing something ? Thanks in advance

Your flow for rowID is like this:

  1. You set the initial state of the parent to be rowId = ""
  2. You pass that to the child component and it gets saved in the child state
  3. You call this.props.handleEdit like this: this.props.handleEdit();
  4. You update your state with rowId: id in handleEdit
  5. The parent rowId will not copied to the child state id because it is only set in the component constructor.

At the beginning, rowId is "", because that is the default in your state of the parent => This will be the id of the child.

The problem is, that you call this.props.handleEdit without an id. This will set your rowId to be undefined in the parent.

You have to set the rowId somewhere in your code, for example in your child component like this:

 this.props.handleEdit(myID); or this.props.handleEdit(this.state.id);

This will set the id and rowID will be defined to whatever you pass to handleEdit.

But this will not update your id in your state within your child component, since the constructor will not be called again after the parent state updates.

To update the child state, you will have to listen to rowId changes with componentDidUpdate or use this.props.rowId directly from the parent component.

componentDidUpdate(prevProps) {
  if (this.props.rowId!== prevProps.rowId) {
    this.setState({id: this.props.rowId});
  }
}

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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