Reputation: 105
A component that renders a preview of filled out forms, as you click on the forms on the left it displays them on the right.
The first handleSwitchReview throws me the React Hooks Rendered more hooks than during the previous render error
The second does not. When I console log the props for example I am getting them 4-5 times when the view with the first function is shown, but not the second, the second only shows 1 time in the console log.
Tried moving the setState around and logging the parents in the console but this component is the only one that's firing a bunch of times and breaking, and maybe I just dont have a firm understanding on how to structure this.
const SimpleFormPreview = (props) => {
//Deconstructing Props
const { childAndButtonWithStylesForPreview } = props;
//Setting State
const [child, setChild] = useState({
childToDisplay: childAndButtonWithStylesForPreview ? childAndButtonWithStylesForPreview[0].child : {}
});
//Deconstructing State
const { childToDisplay } = child;
const handleSwitchReview = (childWithIconArr) => {
setChild({ childToDisplay: childWithIconArr.child });
};
const renderPreview = () => {
if (childToDisplay.hasOwnProperty('schema')) {
return <SimpleFormView children={undefined} schema={childToDisplay.schema} onValChange={{}} onSatisfiedOrPercentageChange={{}} vals={{}} existingLookupOriginalVals={{}} nonStandardKeysInPropInfo={{}} satisfiedOverrides={{}} />;
} else {
var reviewItems = _.map(childToDisplay, function (val, key) {
console.log('here', val, key);
if (!key.startsWith('customer') && (key.startsWith('custom') || key.endsWith('Cost'))) {
//skip rendering these
//they will be attached to the main settings rendering below
return null;
} else {
if (key === '_id' || key === 'id') {
return null;
}
var costEl;
var customEl;
_.each(childToDisplay, function (customOrCostVal, customOrCostKey) {
if (customOrCostKey === 'custom' + key) {
customEl = (
<div
style={{
display: 'inline-block',
marginLeft: 5,
color: 'rgb(222, 222, 0)'
}}>
{'Customized to ' + customOrCostVal.toString()}
</div>
);
}
if (customOrCostKey === key + 'Cost') {
costEl = (
<div
style={{
display: 'inline-block',
color: 'rgba(39, 204, 39, 0.52)',
marginRight: 20
}}>
{'+ $' + customOrCostVal.val}
</div>
);
totalAdditionalCost = totalAdditionalCost + customOrCostVal.val;
}
});
return (
<div key={key}>
{costEl}
<div style={{ display: 'inline-block', marginLeft: 5 }}>{key.toString()}</div>:<div style={{ display: 'inline-block', marginLeft: 5 }}>{val.toString()}</div>
{customEl}
</div>
);
}
});
return reviewItems;
}
};
return (
<Grid container direction='column' justify='flex-start' spacing={0}>
<Grid item xs={12}>
<Grid container wrap='wrap' spacing={0}>
<Grid style={{ position: 'fixed', width: 100 }} container direction='column'>
<div style={{ marginLeft: 'auto', height: 447, overflowY: 'scroll', direction: 'rtl', background: 'transparent' }}>
{_.map(childAndButtonWithStylesForPreview, function (childObj, idx) {
var innerIconElText = '';
// if ((idx + 1) > 99) {
// innerIconElText = '...' + (idx + 1)
// } else {
// innerIconElText = idx + 1
// }
if (childObj.iconEl) {
childObj.iconEl.props.style.boxShadow = childToDisplay.id === childObj.child.id ? 'green 0px 0px 33px 5px' : null;
return <div onClick={() => handleSwitchReview(childObj)} key={idx}>{childObj.iconEl}</div>;
} else {
return (
<Button style={{ boxShadow: childToDisplay.id === childObj.child.id ? 'green 0px 0px 33px 5px' : null, height: 100, margin: '25px', borderRadius: 60 }} key={idx} onClick={() => handleSwitchReview(childObj)}>
<span id='defaultChildIcon' style={{ position: 'relative' }}></span>
<span style={{ marginLeft: 22, marginTop: 10, fontSize: 12, position: 'absolute' }}>{innerIconElText}</span>
</Button>
);
}
})}
</div>
</Grid>
<Grid id={'simpleForm'} style={{ height: '100%', width: '100%', overflow: 'auto' }} container>
<Paper style={{ marginTop: '25px', marginLeft: '165px', padding: '15px', width: '80%' }} elevation={24}>
hello
<div style={{ float: 'right' }}>
<Button id='localSaveBtn' onClick={() => handleSave(document.querySelector('#simpleForm'))} variant='contained' color='secondary' size='large' style={{}}>
Save File
</Button>
</div>
</Paper>
</Grid>
</Grid>
</Grid>
</Grid>
);
};
export default SimpleFormPreview;
Upvotes: 0
Views: 275
Reputation: 105
Mutating the prop directly after the if statement " if (childObj.iconEl) " was causing the app to re render repeatedly.
with cloneElement I was able to have my element will have the original element’s props with the new props merged in shallowly: reactjs.org/docs/react-api.html#cloneelement the error stopped and I was able to achieve the desired result which was to change the box shadow onClick of a button that was passed down to a child element as props.
Below is the code to replace the lines after the " if (childObj.iconEl) " If Condition.
var clonedElementWithInjectedStyles = React.cloneElement(childObj.iconEl, { style: { ...childObj.iconEl.props.style, boxShadow: childToDisplay.id === childObj.child.id ? 'green 0px 0px 33px 5px' : null } });
return (
<div onClick={() => handleSwitchReview(childObj)} key={idx}>
{clonedElementWithInjectedStyles}
</div>
);
Upvotes: 1