0
votes

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

1
Can you show us the parent component, where rowId is saved?Domino987
yes sure, updated my questionEnzo
Post the entire component.Rohit Kashyap
In your child component, use props.rowId instead.Rohit Kashyap
no luck, it's empty because at first rowId is empty but after ajax request i've set to rowIdEnzo

1 Answers

1
votes

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.