简体   繁体   中英

React: How to refresh a component when form submit from another component?

I really need help. I am displaying tree on the left side of the page. Every tree node is linked to the component. On click of node, using routing, I am opening a component on the right side of the page. All the components on the right side have form. How to refresh a tree on the left side of page without refreshing the form component on the right. page contains two components: Left Part of Page: ProductsTreeView Right Part of Page Add_Category component. Form submit Add_Category without refresh right part of page, how to refresh treeview on the left side of page.

Please find the code in the sandbox. This is showing tree: https://codesandbox.io/s/shy-snow-nfce4i

Complete code is in this sandbox: https://codesandbox.io/s/summer-water-ouw2dn Somehow this sandbox is not working.

Please help if I am adding a tree node using Add_Category, form submit should not refresh add_category component, it just only refresh the tree in the left side of the page.

import React, { Component, createRef } from "react";
import XMLParser from "react-xml-parser";
import { Link } from "react-router-dom";
import styled from "styled-components";
import plus from "./plus.gif";
import minus from "./minus.gif";
import paper from "./paper.gif";

const tree = `
<?xml version="1.0" standalone="yes"?>

<tree>

       <entity id="e11" key-id="1" link-page-name="Add_Category">
              <description>Service</description>
              <image>plus.gif</image>
              <imageOpen>minus.gif</imageOpen>
              <entity id="e248" key-id="48" link-page-name="Edit_Category">
                     <description>A_test1_test1</description>
                     <image>plus.gif</image>
                     <imageOpen>minus.gif</imageOpen>
                     <entity id="e3717" key-id="717" link-page-name="Edit_Product">
                           <description>A_SubItem1</description>
                           <image>plus.gif</image>                      <imageNode>de.gif</imageNode>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e45546" key-id="5546" link-page-name="Edit_ProdTemplate">
                                  <description>A_Test_Template</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>
                           </entity>
                     </entity>
              </entity>
              <entity id="e264" key-id="64" link-page-name="Add_Product">
              <description>111AAAA</description>        
              <image>plus.gif</image>       
              <imageOpen>minus.gif</imageOpen>      
            </entity>   
            <entity id="e256" key-id="56" link-page-name="Add_Product">       
              <description>11323789</description>  
              <image>plus.gif</image>     
              <imageOpen>minus.gif</imageOpen>     
            </entity>
              <entity id="e247" key-id="47" link-page-name="Edit_Category">
                     <description>A_test6</description>
                     <image>plus.gif</image>
                     <imageOpen>minus.gif</imageOpen>

                     <entity id="e3716" key-id="716" link-page-name="Edit_Product">
                           <description>A_Item</description>
                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e45545" key-id="5545" link-page-name="Edit_ProdTemplate">
                                  <description>temp1</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

              </entity>

 

       </entity>

       <entity id="e12" key-id="2" link-page-name="Add_Category">

              <description>Sales</description>

              <image>plus.gif</image>

              <imageOpen>minus.gif</imageOpen>

              <entity id="e230" key-id="30" link-page-name="Edit_Category">

                     <description>Gift Cards</description>

                     <image>plus.gif</image>
                  <imageOpen>minus.gif</imageOpen>

                     <entity id="e3421" key-id="421" link-page-name="Edit_Product">

                           <description>Sample Card</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e43308" key-id="3308" link-page-name="Edit_ProdTemplate">

                                  <description>greeting temp</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

                     <entity id="e3422" key-id="422" link-page-name="Edit_Product">

                           <description>De Card</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e43309" key-id="3309" link-page-name="Edit_ProdTemplate">

                                  <description>NS Temp</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

 

              </entity>

              <entity id="e215" key-id="15" link-page-name="Edit_Category">

                     <description>Chck</description>

                     <image>plus.gif</image>

                     <imageOpen>minus.gif</imageOpen>

                     <entity id="e3671" key-id="671" link-page-name="Edit_Product">

                           <description>Add item</description>

                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>

                           <entity id="e45438" key-id="5438" link-page-name="Edit_ProdTemplate">

                                  <description>Ahhhh</description>

                                  <image>paper.gif</image>

                                  <imageOpen>paper.gif</imageOpen>

                           </entity>

                     </entity>

                     <entity id="e3450" key-id="450" link-page-name="Edit_Product">
                           <description>Advtttt</description>
                           <image>plus.gif</image>
                           <imageOpen>minus.gif</imageOpen>
                           <entity id="e43577" key-id="3577" link-page-name="Edit_ProdTemplate">
                                  <description>gggggg</description>
                                  <image>paper.gif</image>
                                  <imageOpen>paper.gif</imageOpen>
                           </entity>
                     </entity>
              </entity>
       </entity>

</tree>
`;

const StyledLI = styled.li`
  list-style-type: none;

  ::before {
    content: "";

    display: inline-flex;

    width: 16px;

    height: 16px;

    ${({ expanded, isPaper }) =>
      `background: url(${
        isPaper === paper ? paper : expanded ? minus : plus
      })};`};
  }
`;

class ProductsTreeView extends Component {
  constructor(props) {
    super(props);

    this.treeView = createRef();
  }

  render() {
    return (
      <div id="TreeView">
        <TreeView
          ref={this.treeView}
          setCurrentNode={this.props.setCurrentNode}
        />
      </div>
    );
  }
}

class Node {
  description = "n/a";

  id = -1;

  key_id = -1;

  linkpagename = "";

  icon = "";

  isActive = false;

  nodes = [];

  constructor(description, id, key_id, icon, linkpagename) {
    this.description = description;

    this.id = id;

    this.key_id = key_id;

    this.icon = icon;

    this.linkpagename = linkpagename;
  }

  static nodesFromXml(xml) {
    const map = (entity, nodes) => {
      const id = entity.attributes["id"];

      const key_id = entity.attributes["key-id"];

      const descriptionText =
        entity.children[
          entity.children.findIndex((child) => child.name === "description")
        ].value;

      const entities = entity.children.filter(
        (child) => child.name === "entity"
      );

      var linkPageName = entity.attributes["link-page-name"];

      linkPageName = linkPageName.replace(".aspx", "");

      const icon =
        entity.children[
          entity.children.findIndex((child) => child.name === "imageOpen")
        ].value;

      const node = new Node(descriptionText, id, key_id, icon, linkPageName);

      nodes.push(node);

      entities.forEach((entity) => map(entity, node.nodes));
    };

    const parsedData = new XMLParser().parseFromString(xml);

    const entities = parsedData.children.filter(
      (child) => child.name === "entity"
    );

    const nodes = [];

    entities.forEach((entity) => map(entity, nodes));

    return nodes;
  }
}

class TreeView extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      //  nodes: []
      nodes: Node.nodesFromXml(tree)
    };

    this.toggleNode = this.toggleNode.bind(this);

    this.CollapseAll = this.CollapseAll.bind(this);

    this.ExpandAll = this.ExpandAll.bind(this);
  }

  componentDidMount() {
    // axios
    //   .get(tree, { "Content-Type": "application/xml; charset=utf-8" })
    //   .then((response) =>{
    //     console.log({ response })
    //     // this.setState({ nodes: Node.nodesFromXml(response.data) })
    //   })
    //   .catch((error) => console.error("Error:", error));
  }

  render() {
    const nodes = this.state.nodes;

    return (
      <div>
        <table width="100%">
          <tr>
            <td width="50%" align="left">
              &nbsp;&nbsp;<b>Products</b>
            </td>
            <td width="50%" style={{ textAlign: "right" }}></td>
          </tr>
        </table>

        <ul>
          {nodes.map((node) => (
            <TreeNode
              id={node.id}
              key={node.key_id}
              node={node}
              onToggle={this.toggleNode}
              setCurrentNode={this.props.setCurrentNode}
            />
          ))}
        </ul>
      </div>
    );
  }

  toggleNode(node) {
    const { nodes } = this.state;

    this.props.setCurrentNode(node);

    function _toggleNode(currentNode, node, isActive) {
      if (isActive !== undefined) {
        currentNode.isActive = isActive;
      } else if (currentNode.id === node.id) {
        if (currentNode.key_id === node.key_id) {
          currentNode.isActive = !currentNode.isActive;
        }
      }

      currentNode.nodes.forEach((childNode) =>
        _toggleNode(childNode, node, currentNode.isActive ? undefined : false)
      );
    }

    nodes.forEach((currentNode) => _toggleNode(currentNode, node));

    this.setState((state) => (state.nodes = nodes));
  }

  CollapseAll() {
    const { nodes } = this.state;

    function _collapseAll(currentNode) {
      currentNode.isActive = false;

      currentNode.nodes.forEach((childNode) => _collapseAll(childNode));
    }

    nodes.forEach((currentNode) => _collapseAll(currentNode));

    this.setState((state) => (state.nodes = nodes));
  }

  ExpandAll() {
    const { nodes } = this.state;

    function _expandAll(currentNode) {
      currentNode.isActive = true;

      currentNode.nodes.forEach((childNode) => _expandAll(childNode));
    }

    nodes.forEach((currentNode) => _expandAll(currentNode));

    this.setState((state) => (state.nodes = nodes));
  }
}

class TreeNode extends React.Component {
  render() {
    const { node, onToggle } = this.props;

    const activeChildren =
      node.isActive && node.nodes.length ? (
        <ul style={{ paddingLeft: "1.8rem" }}>
          {node.nodes.map((node) => (
            <TreeNode
              id={node.id}
              key={node.key_id}
              node={node}
              onToggle={onToggle}
            />
          ))}
        </ul>
      ) : null;

    return (
      <Link
        to={node.linkpagename}
        key={node.key_id}
        onClick={(event) => {
          event.stopPropagation();

          onToggle(node);
        }}
        style={{ textDecoration: "none", color: "#000000" }}
      >
        <StyledLI
          id={node.id}
          expanded={node.isActive}
          isPaper={node.icon}
          isLeaf={!node.nodes.length}
        >
          {node.description}

          {/*- {node.key_id} - {node.linkpagename}*/}

          {activeChildren}
        </StyledLI>
      </Link>
    );
  }
}

export default ProductsTreeView;
------------------------Add_Category.js

import React from 'react'

 

export class Add_Category extends React.Component {

       constructor(props) {

             super(props);

             this.state = {

                    ID: "",

                    CategoryName: "",
                    ValidationStatus:"",

             };

             this.handleChange = this.handleChange.bind(this);

             this.handleSubmit = this.handleSubmit.bind(this);

       }

 

       handleChange(event) {

             this.setState({ CategoryName: event.target.value });

       }

 

       handleSubmit(event) {

             event.preventDefault();

            

       const ID = this.props.key_id;

                    const CategoryName    = this.state.CategoryName;

                    const data = {

                                        ID,

                                        CategoryName

                    }

                    fetch("url", {

                           method: 'POST',

                           headers: { 'Content-Type': 'application/json' },

                           credentials: 'include',

                           body: JSON.stringify(data),

                    })

                           .then(response => response.json())

                           .then((data) => {

                                 this.setState({

                                        ValidationStatus: data

                                 })

                           })

                           .then(response => { window.location.href = "/"; })

                           .catch(error => console.error('Error:', error)) ;

             }

       }

      

 

       render() {

        return (

                    <div>
  <form onSubmit={this.handleSubmit}>

<input type="text" value={this.state.CategoryName} onChange={this.handleChange} size="50" maxLength="50" />
        <button type="Submit" className="SaveButton">Submit</button>



</form>

</div>



);

}

}
 

export default Add_Category;
-------------------------Home.js
import React, { createRef } from "react";

import { TabContent, TabPane, Nav, NavItem, NavLink } from "reactstrap";

import { Route } from "react-router-dom";

import classnames from "classnames";

import "./styles.css";

import ProductsTree from "./ProductsTreeView";
import Add_Category from "./Add_Category";

const initialState = {
  currentNode: {},

  data: "",

  activeTab: "1"
};

class Home extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);

    this.state = initialState;

    this.setCurrentNode = this.setCurrentNode.bind(this);

    this.productsTree = createRef();
  }

  setCurrentNode(node) {
    this.setState({ currentNode: node });
  }

  toggle(tab) {
    if (this.state.activeTab !== tab) {
      this.setState({
        activeTab: tab
      });
    }

    this.productsTree.current.treeView.current.CollapseAll();
  }

  ExpandAll() {
    this.productsTree.current.treeView.current.ExpandAll();
  }

  CollapseAll() {
    this.productsTree.current.treeView.current.CollapseAll();
  }

  render() {
    return (
      <div>
        <table className="Container">
          <tbody>
            <tr width="100%">
              <td className="TreeContainer">
                <table width="100%" border="0" cellSpacing="0" cellPadding="0">
                  <tbody>
                    <tr className="trIndex_Products" width="100%">
                      <td align="left" nowrap="true">
                        <Nav tabs height="15px">
                          <NavItem>
                            <NavLink
                              className={classnames({
                                active: this.state.activeTab === "1"
                              })}
                              onClick={() => {
                                this.toggle("1");
                              }}
                            >
                              <b>Products</b>
                            </NavLink>
                          </NavItem>
                          <NavItem>
                            <NavLink
                              className={classnames({
                                active: this.state.activeTab === "2"
                              })}
                              onClick={() => {
                                this.toggle("2");
                              }}
                            >
                              <b>Sales</b>
                            </NavLink>
                          </NavItem>
                          <NavItem>
                            <NavLink
                              onClick={() => {
                                this.ExpandAll();
                              }}
                            >
                              <b>Expand</b>
                            </NavLink>
                          </NavItem>{" "}
                          &nbsp;&nbsp;
                          <NavItem>
                            <NavLink
                              onClick={() => {
                                this.CollapseAll();
                              }}
                            >
                              <b>Minimize</b>
                            </NavLink>
                          </NavItem>
                        </Nav>
                      </td>
                    </tr>
                  </tbody>
                </table>{" "}
                <br />
                <TabContent activeTab={this.state.activeTab}>
                  <TabPane tabId="1">
                    <div id="ProdTree" className="tree">
                      <ProductsTree
                        ref={this.productsTree}
                        setCurrentNode={this.setCurrentNode}
                      />
                    </div>
                  </TabPane>

                  <TabPane tabId="2">
                    <div className="tree"></div>
                  </TabPane>
                </TabContent>
              </td>

              <td className="BodyContainer">
                <table width="100%" border="0" cellSpacing="0" cellPadding="0">
                  <tbody>
                    <tr width="100%">
                      <td>
                        <Route path="/Add_Category">
                          <Add_Category
                            key_id={this.state.currentNode.key_id}
                          />
                        </Route>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
}

export default Home;

If I understand your problem correctly you want to refresh the sibling component. By using a state hook you can achieve this. Refer to the code on the below link.

https://learntechatyourpace.blogspot.com/2022/12/react-how-to-refresh-sibling-components.html

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