{"id":533,"date":"2020-07-14T15:23:12","date_gmt":"2020-07-14T15:23:12","guid":{"rendered":"https:\/\/jmrowe.com\/blog\/?p=533"},"modified":"2020-07-14T17:45:10","modified_gmt":"2020-07-14T17:45:10","slug":"react-js-creating-a-parent-component-with-variable-amount-of-child-components","status":"publish","type":"post","link":"https:\/\/jmrowe.com\/blog\/react-js-creating-a-parent-component-with-variable-amount-of-child-components\/","title":{"rendered":"React js &#8211; creating a parent component with variable amount of child components."},"content":{"rendered":"<p><strong>Problem:\u00a0<\/strong>Had a &#8220;option&#8221; box I was creating where there could be any number of &#8220;tags&#8221; that can be added for that option.<\/p>\n<p><strong>Solution:\u00a0<\/strong>Created a context local to the parent\/children components only, kept a separate variable to manually track how many &#8220;groups&#8221; of options has been requested by the user. Used an array of objects and updated according to index which is sent in as a prop to each set of options. Example code<\/p>\n<pre class=\"lang:default decode:true \">\/\/ in RewriteAjaxInput.js which contains the parent and children.\r\n\/\/ variables to be used in context\r\n\r\nconst [ruleArrayObject, setRuleArrayObject]=useImmer([\r\n        {\r\n            optionalBase:\"default1\",\r\n            tag:\"tag1\",\r\n            regexPattern:\"static\"\r\n        }\r\n    ]);\r\nconst [numberOfRules,setNumberOfRules]=React.useState(1);\r\n\r\n\/\/ created context\r\n\r\n&lt;ReWriteAjaxRulesContext.Provider value={[ruleArrayObject, setRuleArrayObject,numberOfRules,setNumberOfRules]}&gt;\r\n   &lt;ReWriteAjaxRules \/&gt;\r\n&lt;\/ReWriteAjaxRulesContext.Provider&gt;\r\n\r\n\r\n\/\/ also in same class is the button to add more sets of options\r\n\/\/ that method is below:\r\n    const addRule=(e)=&gt;{\r\n        \/\/ do something\r\n        setRuleArrayObject(draft=&gt;{draft.push(\r\n            {\r\n                optionalBase:\"dsf\",\r\n                tag:\"sdfsf\",\r\n                regexPattern:\"static\"\r\n            }\r\n\r\n        )});\r\n\r\n        setNumberOfRules(numberOfRules+1);\r\n    }\r\n\r\n\/\/ it basically adds another dummy object \r\n\/\/to the array and increases numberOfRules count to +1<\/pre>\n<p>Here are the Parent and child components<\/p>\n<p>Parent:<\/p>\n<pre class=\"lang:default decode:true \">\/\/ ReWriteAjaxRules ( parent )\r\nimport React from \"react\";\r\nimport ReWriteAjaxRule from \".\/ReWriteAjaxRule\";\r\nimport ReWriteAjaxRulesContext from \"..\/..\/..\/..\/contexts\/ReWriteAjaxRulesContext\";\r\n\";\r\n\r\nconst ReWriteAjaxRules= props=&gt;{\r\n  \r\n\r\nconst createLayout=()=&gt;{\r\n    let result=[];\r\n    for(let i=0;i&lt;numberOfRules;i++){\r\n\r\n        result.push(&lt;ReWriteAjaxRule\r\n        index={i}\r\n        \/&gt;)\r\n    }\r\n\r\nreturn result;\r\n    }\r\n    return(  &lt;div&gt;\r\n        {createLayout()}\r\n    &lt;\/div&gt;);\r\n}\r\n\r\nexport default ReWriteAjaxRules;\r\n\r\n<\/pre>\n<p>Child:<\/p>\n<pre class=\"lang:default decode:true \">\/\/ReWriteAjaxRule ( child )\r\nimport React from \"react\";\r\nimport {InputLabel, MenuItem, Select, TextField} from \"@material-ui\/core\";\r\nimport ReWriteAjaxRulesContext from \"..\/..\/..\/..\/contexts\/ReWriteAjaxRulesContext\";\r\n\r\nconst ReWriteAjaxRule= props=&gt;{\r\n    const [ruleArrayObject, setRuleArrayObject,numberOfRules,setNumberOfRules]=React.useContext(ReWriteAjaxRulesContext);\r\n\r\n    const sendBaseUpdate=(e)=&gt;{\r\n      \/\/ we do the below check on e.target.value to avoid edge cases \r\n      \/\/ where rerendered elements return a null value for e.target.value\r\n        let newValue=e.target.value?e.target.value:\"\";\r\n\r\n       \/\/ uses immer instead of state so it's easier to mutate a \r\n       \/\/ particular index in the array \r\n        setRuleArrayObject(draft=&gt; {\r\n            draft[props.index].optionalBase = newValue;\r\n        } );\r\n\r\n    }\r\n    const sendTagUpdate=(e)=&gt;{\r\n        let newValue=e.target.value?e.target.value:\"\";\r\n        setRuleArrayObject(draft=&gt; {\r\n            draft[props.index].tag = newValue;\r\n        } );\r\n\r\n    }\r\n    const sendRegexPatternUpdate=(e)=&gt;{\r\n        let newValue=e.target.value?e.target.value:\"\";\r\n        setRuleArrayObject(draft=&gt; {\r\n            draft[props.index].regexPattern = newValue;\r\n        } );\r\n\r\n    }\r\n    return(  &lt;div className={\"reWriteRuleRow\"}&gt;\r\n        &lt;TextField label=\"Base:\"\r\n                   helperText=\"Optional Base of Rewrite\"\r\n                   value={ruleArrayObject[props.index].optionalBase}\r\n                   onChange={sendBaseUpdate}\r\n                   type=\"text\"\r\n                   style={{marginRight:\"10px\"}}\r\n        \/&gt;\r\n        &lt;TextField label=\"GET Variable:\"\r\n            \/\/ helperText=\"Shortcode tag in the content. e.g. [tag]\"\r\n                   value={ruleArrayObject[props.index].tag}\r\n                   onChange={sendTagUpdate}\r\n                   type=\"text\"\r\n                   style={{marginLeft:\"10px\"}}\r\n        \/&gt;\r\n        &lt;InputLabel &gt;\r\n            Get Variable Type(regex):\r\n            &lt;Select\r\n                labelId=\"label\"\r\n                id=\"select\"\r\n                value={ruleArrayObject[props.index].regexPattern}\r\n                onChange={sendRegexPatternUpdate}\r\n                style={{marginLeft:\"10px\"}}\r\n            &gt;\r\n                &lt;MenuItem value=\"static\"&gt;Static Value&lt;\/MenuItem&gt;\r\n                &lt;MenuItem value=\"any\"&gt;Any Value&lt;\/MenuItem&gt;\r\n                &lt;MenuItem value=\"digit\"&gt;Only digit Value&lt;\/MenuItem&gt;\r\n            &lt;\/Select&gt;\r\n            {\/*&lt;br\/&gt;&lt;small&gt;Self-closing shortcode: [tag]&lt;\/small&gt;*\/}\r\n            {\/*&lt;br\/&gt;&lt;small&gt;Enclosing shortcode: [tag]content[\/tag]&lt;\/small&gt;*\/}\r\n        &lt;\/InputLabel&gt;\r\n\r\n    &lt;\/div&gt;);\r\n}\r\n\r\nexport default ReWriteAjaxRule;<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Problem:\u00a0Had a &#8220;option&#8221; box I was creating where there could be any number of &#8220;tags&#8221; that can be added for that option. Solution:\u00a0Created a context local to the parent\/children components only, kept a separate variable to manually track how many &#8220;groups&#8221; of options has been requested by the user. Used an array of objects and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":["post-533","post","type-post","status-publish","format-standard","hentry","category-javascript"],"_links":{"self":[{"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/posts\/533","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/comments?post=533"}],"version-history":[{"count":5,"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/posts\/533\/revisions"}],"predecessor-version":[{"id":538,"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/posts\/533\/revisions\/538"}],"wp:attachment":[{"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/media?parent=533"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/categories?post=533"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jmrowe.com\/blog\/wp-json\/wp\/v2\/tags?post=533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}