If statement & PopUp window in React

Click For Summary
SUMMARY

The discussion centers on implementing conditional pop-up messages in React when a specific radio button is selected. Users explored using the 'reactjs-popup' library to trigger a pop-up when the "Yes" option is selected, and clarified the distinction between pop-ups and modal dialogs, referencing Material UI's Dialog component. Key issues included handling button actions to close the pop-up and ensuring compatibility with TypeScript and JavaScript versions of the Material UI documentation.

PREREQUISITES
  • Understanding of React components and state management
  • Familiarity with the 'reactjs-popup' library
  • Knowledge of Material UI components, specifically Dialog
  • Basic understanding of JavaScript and TypeScript differences
NEXT STEPS
  • Learn how to implement conditional rendering in React
  • Explore the 'reactjs-popup' documentation for advanced usage
  • Study Material UI Dialog component for modal implementations
  • Investigate event handling in React for form submissions
USEFUL FOR

Frontend developers, React enthusiasts, and anyone looking to enhance user interaction through pop-ups and modals in web applications.

  • #31
I had tried the following :

JavaScript:
   const [dataObj, setDataObj] = useState([]); 
 
   useEffect(() => {
        fetch('https://giant-db-connection.onrender.com/opc_ua_tree/')
            .then((res) => res.json())
            .then((data) => {
                setDataObj(data[0]['tree_structure'][0].Nodes[0]);
                console.log(dataObj.DisplayName);
                while (dataObj.Nodes) {
                    for (let i = 0; i < dataObj.Nodes.length; i++) {
                        console.log(dataObj.Nodes[i].DisplayName);
                    }
                    setDataObj(dataObj.Nodes);
                }
            });
    }, []);
I want to display all the DisplayNames. First I did it with many for loops and it worked, now I am trying to write it with less code by setting dataObj.Nodes into the current dataObj. Is this correct so far?

Can the result be also in a TreeView (TreeItem) ? 🤔
 
Technology news on Phys.org
  • #32
mathmari said:
I want to display all the DisplayNames. First I did it with many for loops and it worked, now I am trying to write it with less code by setting dataObj.Nodes into the current dataObj. Is this correct so far?
I wouldn't do it that way. Either the date in the tree is static, in which case there is no point in using a reactive object for it, or it is dynamic in which case you don't want to be managing it inside a component - it should be in a Redux store.

mathmari said:
Can the result be also in a TreeView (TreeItem) ?
Of course, see the example at https://mui.com/material-ui/react-tree-view/#rich-object. You may want to pre-parse the data into a much more normalized format.
 
  • #33
pbuk said:
I wouldn't do it that way. Either the date in the tree is static, in which case there is no point in using a reactive object for it, or it is dynamic in which case you don't want to be managing it inside a component - it should be in a Redux store.

Could you explain that further to me? Do we have to store the data instead of dataObj in a Redux store? 🤔
 
  • #34
So we save the whole tree in a Redux store and then we we get the component that we want to print with useSelector ? 🤔
 
  • #35
Well I'd be inclined to flatten the tree in the response into an object with the id as the key:
JavaScript:
{
  'id-1234': {
    title: '...',
    children: [
      'id-2345',
      'id-9876',
    ],
  },
  'id-2345': {
    // ...
  },
  // ...
}
which will make it much easier to use, but otherwise, yes.
 
  • Like
Likes   Reactions: mathmari
  • #36
pbuk said:
Well I'd be inclined to flatten the tree in the response into an object with the id as the key:
JavaScript:
{
  'id-1234': {
    title: '...',
    children: [
      'id-2345',
      'id-9876',
    ],
  },
  'id-2345': {
    // ...
  },
  // ...
}
which will make it much easier to use, but otherwise, yes.

I haven't understood what you mean. Could you explain that further to me?
 
  • #37
Do you mean how to store the tree in a redux tree or what do you mean by the above?
 
  • #38
mathmari said:
I haven't understood what you mean. Could you explain that further to me?
Well here is the beginning of the response:
JavaScript:
[
  {
    "tree_structure": [
      {
        "TypeDefinition": "Namespace",
        "IndexName": "0:Objects",
        "URI": "http://opcfoundation.org/UA/",
        "Nodes": [
          {
            "DisplayName": "Objects",
            "Attributes": [
              {
                "NodeId": "i=85",
                "NodeClass": "Object",
                "BrowseName": "Objects",
                "DisplayName": "Objects",
                "Description": null,
                "WriteMask": null,
                "UserWriteMask": null,
                "EventNotifier": null
              }
            ],
            "Nodes": [
              {
                "DisplayName": "Server",
                "Attributes": [
                  {
                    "NodeId": "i=2253",
                    "NodeClass": "Object",
                    "BrowseName": "Server",
                    "DisplayName": "Server",
                    "Description": null,
                    "WriteMask": null,
                    "UserWriteMask": null,
                    "EventNotifier": ["SubscribeToEvents"]
                  }
                ],
                "Nodes": [
                  {
                    "DisplayName": "ServerStatus",
                    "Attributes": [
                      {
                        "NodeId": "i=2256",
                        "NodeClass": "Variable",
                        "BrowseName": "ServerStatus",
                        "DisplayName": "ServerStatus",
                        "Description": null,
                        "WriteMask": null,
                        "UserWriteMask": null,
                        "Value": "ServerStatusDataType(StartTime=datetime.datetime(2022, 9, 27, 7, 45, 53, 181000), CurrentTime=datetime.datetime(2022, 9, 27, 14, 57, 5, 827000), State=<ServerState.Running: 0>, BuildInfo_=BuildInfo(ProductUri='urn:prosysopc.com:OPCUA:SimulationServer', ManufacturerName='Prosys OPC Ltd.', ProductName='SimulationServer@DESKTOP-VN3GQ4Q', SoftwareVersion='5.3.0', BuildNumber='64', BuildDate=datetime.datetime(1970, 1, 1, 0, 0)), SecondsTillShutdown=0, ShutdownReason=LocalizedText(Locale='', Text=''))",
                        "DataType": "ExtensionObject",
                        "ValueRank": "Scalar",
                        "AccessLevel": ["CurrentRead"],
                        "UserAccessLevel": ["CurrentRead"],
                        "MinimumSamplingInterval": 1000.0,
                        "Historizing": false
                      }
                    ],
Let's say you want to display the minumum sampling interval for the node with id "i=2256": this is not going to be easy. If instead you parse this tree into a flat structure:
JavaScript:
{
  "tree_structure": {
    "TypeDefinition": "Namespace",
    "IndexName": "0:Objects",
    "URI": "http://opcfoundation.org/UA/",
    // Note the change from an array to a POJO.
    "Nodes": {
      "i=85" : {
        "DisplayName": "Objects",
        "Attributes": [
          {
            "NodeId": "i=85",
            "NodeClass": "Object",
            "BrowseName": "Objects",
            "DisplayName": "Objects",
            "Description": null,
            "WriteMask": null,
            "UserWriteMask": null,
            "EventNotifier": null
          },
        ],
        parent: null,
        children: [
          "i=2253",
        ],
      },

      "i-2253": {
        "DisplayName": "Server",
        "Attributes": [
          {
            "NodeId": "i=2253",
            "NodeClass": "Object",
            "BrowseName": "Server",
            "DisplayName": "Server",
            "Description": null,
            "WriteMask": null,
            "UserWriteMask": null,
            "EventNotifier": ["SubscribeToEvents"]
          }
        ],
        parent: "i=85",
        children: [
          "i=2256",
        ],
      },

      "i=2256": {
        "DisplayName": "ServerStatus",
        "Attributes": [
          {
            "NodeId": "i=2256",
            "NodeClass": "Variable",
            "BrowseName": "ServerStatus",
            "DisplayName": "ServerStatus",
            "Description": null,
            "WriteMask": null,
            "UserWriteMask": null,
            "Value": "ServerStatusDataType(StartTime=datetime.datetime(2022, 9, 27, 7, 45, 53, 181000), CurrentTime=datetime.datetime(2022, 9, 27, 14, 57, 5, 827000), State=<ServerState.Running: 0>, BuildInfo_=BuildInfo(ProductUri='urn:prosysopc.com:OPCUA:SimulationServer', ManufacturerName='Prosys OPC Ltd.', ProductName='SimulationServer@DESKTOP-VN3GQ4Q', SoftwareVersion='5.3.0', BuildNumber='64', BuildDate=datetime.datetime(1970, 1, 1, 0, 0)), SecondsTillShutdown=0, ShutdownReason=LocalizedText(Locale='', Text=''))",
            "DataType": "ExtensionObject",
            "ValueRank": "Scalar",
            "AccessLevel": ["CurrentRead"],
            "UserAccessLevel": ["CurrentRead"],
            "MinimumSamplingInterval": 1000.0,
            "Historizing": false
          }
        ],
        parent: "i=2253",
        children: [
          // ...
        ],
      },
      // More nodes.
it's going to be much easier, it's just data.tree_structure.Nodes['i=2253'].Attributes[0].MinimumSamplingInterval
 
  • Like
Likes   Reactions: mathmari
  • #39
And using the redux store this is possible?
 
  • #40
For the beginning I tried to do that with a non elegant way, to get all data by for loops, I used 3 for loops. I am not reallt sure if I print it correctly with the <TreeView>, could you take a look at it ?

JavaScript:
    const [dataObj, setDataObj] = useState([]);
    
    useEffect(() => {
        fetch('https://giant-db-connection.onrender.com/opc_ua_tree/')
            .then((res) => res.json())
            .then((data) => {
                setDataObj(data[0]['tree_structure'][0].Nodes[0]);
                console.log(data[0]['tree_structure'][0].Nodes[0].DisplayName);
                <TreeView
                    aria-label="file system navigator"
                    sx={{ flexGrow: 1, overflowY: 'auto' }}
                    style={{ height: '34vh', width: '100%' }}
                >
                    <TreeItem nodeId={data[0]['tree_structure'][0].Nodes[0].DisplayName} label={data[0]['tree_structure'][0].Nodes[0].DisplayName}>
                        for (let i = 0; i < data[0]['tree_structure'][0].Nodes[0].Nodes.length; i++) {
                            console.log(data[0]['tree_structure'][0].Nodes[0].Nodes[i].DisplayName);
                            <TreeItem nodeId={data[0]['tree_structure'][0].Nodes[0].Nodes[i].DisplayName} label={data[0]['tree_structure'][0].Nodes[0].Nodes[i].DisplayName}>
                                for (let j = 0; j < data[0]['tree_structure'][0].Nodes[0].Nodes[i].Nodes.length; j++) {
                                    console.log(data[0]['tree_structure'][0].Nodes[0].Nodes[i].Nodes[j].DisplayName);
                                    <TreeItem nodeId={data[0]['tree_structure'][0].Nodes[0].Nodes[i].Nodes[j].DisplayName} label={data[0]['tree_structure'][0].Nodes[0].Nodes[i].Nodes[j].DisplayName} />
                                }
                            </TreeItem>
                        }
                    </TreeItem>
                </TreeView>
            });
    }, []);
🤔
 
Last edited:
  • #41
Or isn't it possible to use a for-loop inside the TreeView? Do we maybe have to use an extra function for that? 🤔
 
  • #42
mathmari said:
For the beginning I tried to do that with a non elegant way, to get all data by for loops, I used 3 for loops.
That won't work. You need to build it recursively, something like this:
JavaScript:
  const tree = {
    server: null,
    treeId: null,
    rootNodeId: null,
    nodes: {},
  };

  const loadTree = async () => {
    const data = await fetchTree();
    tree.server = data[0].server;
    tree.treeId = data[0].tree_id;
    tree.nodes = {};
    const { id } = parseNode(data[0].tree_structure[0].Nodes[0], tree.nodes);
    tree.rootNodeId = id;
  };

  const parseNode = (rawNode, nodes) => {
    // Recursively parse the child nodes, adding to this nodes children.
    const children = [];
    (rawNode.Nodes ?? []).forEach((item) => {
      const { id } = parseNode(item, nodes);
      children.push(id);
    });

    // Create this node.
    const node = {
      id: rawNode.Attributes[0].NodeId,
      title: rawNode.DisplayName,
      children,
      attributes: rawNode.Attributes,
    };

    // Save this node to the dictionary.
    nodes[id] = node;

    // Return the node so the caller can get the id.
    return node;
  };
 
  • Like
Likes   Reactions: mathmari
  • #43
pbuk said:
That won't work. You need to build it recursively, something like this:
JavaScript:
  const tree = {
    server: null,
    treeId: null,
    rootNodeId: null,
    nodes: {},
  };

  const loadTree = async () => {
    const data = await fetchTree();
    tree.server = data[0].server;
    tree.treeId = data[0].tree_id;
    tree.nodes = {};
    const { id } = parseNode(data[0].tree_structure[0].Nodes[0], tree.nodes);
    tree.rootNodeId = id;
  };

  const parseNode = (rawNode, nodes) => {
    // Recursively parse the child nodes, adding to this nodes children.
    const children = [];
    (rawNode.Nodes ?? []).forEach((item) => {
      const { id } = parseNode(item, nodes);
      children.push(id);
    });

    // Create this node.
    const node = {
      id: rawNode.Attributes[0].NodeId,
      title: rawNode.DisplayName,
      children,
      attributes: rawNode.Attributes,
    };

    // Save this node to the dictionary.
    nodes[id] = node;

    // Return the node so the caller can get the id.
    return node;
  };

When we initialize the tree, the keys are the one of the first level of the endpoint ? I mean the following :

1667205785313.png
Could you explain to me the function loadTree ? According to the picture I loaded above we have :

tree.server = data[0].server = 41
tree.treeId = data[0].tree_id = 19

Or not? Could you explain to me the following part?

tree.nodes = {};
const { id } = parseNode(data[0].tree_structure[0].Nodes[0], tree.nodes);
tree.rootNodeId = id;With the function parseNode do we parse through all children nodes?

🤔
 
  • #44
Is the idea to buid the tree that we get from the API again from scratch? 🤔
 
  • #45
mathmari said:
Is the idea to buid the tree that we get from the API again from scratch? 🤔
Yes. Working with a nested tree is practically impossible so this is standard practice.

Rather than explain every element I have created a basic but fully working application in plain JavaScript with no dependencies. You can see the code as a GitHub gist and you can see it working below. Note that sometimes the API does not respond first time, I guess this is due to some limitations on the, possibly free, cloud service.

The code doesn't have many comments in, that is deliberate so you can work through it and see how it all works, and then convert it to React.js using your component libraries of choice, and if you wish Redux (although if all you are going to do is display the data you fetch there is no need to use Redux for this).

 
Last edited:
  • #46
mathmari said:
Is the idea to buid the tree that we get from the API again from scratch? 🤔
Of course if whoever had designed the API had done a better job we wouldn't have to do this.

There are some other odd things about the API response, for instance why is Attributes an array with a single element? Why do the id's not have a regular form: many start with "i=" but some look like e.g. "ns=1;s=79f4049c-8266-4758-9c5a-0013e39273d7/0:SessionDiagnostics/0:ActualSessionTimeout"? Why do some nodes exist at more than one point in the tree (hopefully with the same values) e.g. i=2341?

These are rhetorical questions, I think I'm done here.
 

Similar threads

  • · Replies 10 ·
Replies
10
Views
3K
Replies
24
Views
2K
  • · Replies 23 ·
Replies
23
Views
2K
  • · Replies 16 ·
Replies
16
Views
5K
  • · Replies 4 ·
Replies
4
Views
4K
  • · Replies 25 ·
Replies
25
Views
2K
  • · Replies 4 ·
Replies
4
Views
6K
  • · Replies 12 ·
Replies
12
Views
2K
  • · Replies 6 ·
Replies
6
Views
4K
  • · Replies 1 ·
Replies
1
Views
2K