React - Carbon Design System - Transition in right sidebar not working - reactjs

I'm trying to use Carbon Design System for a project, and I need some help with the UI Shell.
The transition of the right sidebar is not working properly.
Here is the working example, see how smooth it opens and closes (see live example):
Here is the example with issues. There's no transition (see live example):
I think it's related to how High Order Components work. Here's my theory:
HeaderPanel is being rendered inside the HeaderContainer, which is a High Order Component.
When the state variable switchCollapsed changes, the HeaderContainer is rendered entirely again.
So this would explain why there's no transition.
I'm new to React, and this theory is based on my React knowledge until now. Please correct me if I'm wrong
Here's a piece of the code of the second example (simplified for the brevity of this post). See the entire code here
class App extends React.Component {
constructor(props) {
super(props);
this.toggleSwitch = this.toggleSwitch.bind(this);
this.state = { switchCollapsed: true };
}
toggleSwitch() {
this.setState(state => ({
switchCollapsed: !state.switchCollapsed
}));
}
render() {
return (
<div className="container">
<HeaderContainer
render={({ isSideNavExpanded, onClickSideNavExpand }) => (
<>
<Header aria-label="IBM Platform Name">
<HeaderMenuButton
onClick={onClickSideNavExpand}
isActive={isSideNavExpanded}
/>
<HeaderGlobalBar>
<HeaderGlobalAction onClick={this.toggleSwitch}>
<UserAvatar20 />
</HeaderGlobalAction>
</HeaderGlobalBar>
<HeaderPanel
aria-label="Header Panel"
expanded={!this.state.switchCollapsed}
/>
<SideNav
aria-label="Side navigation"
expanded={isSideNavExpanded}
>
<SideNavItems>
</SideNavItems>
</SideNav>
</Header>
<StoryContent />
</>
)}
/>
</div>
);
}
}
render(<App />, document.getElementById("root"));
Moreover, if I change the property on React Dev Tools, the transition work!

Related

Clarity Forms in React, fields not working

I have a body of clarity forms that have been prepared for an Angular application and I'm trying to use them in React. However even getting the simplest form to work is beyond me right now, there's inadequate examples and documentation and I'm not a frontend developer. Based on the almost zero examples I can find I'm guessing very few people are using Clarity Forms in React.
Here's an example form with multiple attempts to get the CdsInput field to do something. Oddly I got onClick to work but I can't type in the field on the form when it displays.
render() {
return (
<main cds-layout="p:lg vertical gap:lg" cds-text="body">
<h1 cds-text="heading">Clarity in React</h1>
{this.state.show ? (
<CdsAlertGroup status="warning">
<CdsAlert onCloseChange={() => this.setState({ show: false })} closable>Hello World</CdsAlert>
</CdsAlertGroup>
) : (
''
)}
<CdsButton status="success" onClick={() => this.setState({ show: true })}>
Show Alert
</CdsButton>
<CdsInput type="text" id="formFields_5" placeholder="Email" defaultValue="DEFAULT TEXT!" onClick={() => this.setState({ show: false })} >
Text inside tags
</CdsInput>
</main>
);
}
So clicking on the field influences the alert so onClick works, but I can't type in the box and it's empty.
I've consulted the example React app on the Clarity Design System website, but it only shows some components and icons, it gives no example of input/select/interactive controls except buttons.
I am aware that React doesn't support WebComponents and so Clarity Forms isn't a natural fit, but when I import #cds/react am I compensating for this deficiency or do I also have to put a ref on the CdsInput ... I did try that but got too many errors about types and other things:
inputRef: React.RefObject<typeof CdsInput>;
constructor(props: any) {
super(props);
this.state = {
show: false,
};
this.inputRef = React.createRef<typeof CdsInput>();
}
componentDidMount() {
this.inputRef.current.nativeElement.then(element => {
element.focus();
});
}
render() {
return (
... <CdsInput ref={this.inputRef} >HEY THERE</CdsInput> ...
Does anyone know of a simple but functional example of a Clarity Form working in React using #cds/react that I could refer to?

What's the best way to create a hamburger menu from scratch in Reactjs without using Hooks?

I'm trying to create a hamburger menu within React using state and onClick, from scratch. I have no experience with React Hooks so am trying to avoid that. The solution I have right now works, but is slow and glitchy and I have a feeling the code is quite flawed.
I deployed it anyways to test it out in live, and it's not working well at all in mobile chrome browser (https://vigilant-leavitt-a88a0e.netlify.app/). (though at least the background-color works when inspecting on a browser at mobile dimensions).
Can anyone tell me what I'm doing wrong here, or how this could be cleaned up? I have app.js feeding props to header.js.
Thank you!
App.js
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
menuOpen: false
};
}
componentDidMount() {
this.setState({
menuOpen: false
});
}
handleMenuClick = () => {
this.setState({ menuOpen: true });
}
handleCloseMenuClick = () => {
this.setState({ menuOpen: false });
}
render() {
return (
<>
<Router>
<Header
menuOpen={this.state.menuOpen}
handleMenuClick={this.handleMenuClick}
handleCloseMenuClick={this.handleCloseMenuClick} />
<Switch>
<Route path="/resources"><Resources /></Route>
<Route path="/team"><Team /></Route>
<Route path="/faq"><Faq /></Route>
<Route path="/fees"><Fees /></Route>
<Route path="/"><Home /></Route>
</Switch>
<Footer />
</Router>
</>
);
}
}
Header.js
<div className="header__navburger">
{props.menuOpen === false ?
(<img
className="header__hamburger-icon"
alt="Menu"
src={menuicon}
onClick={() => props.handleMenuClick()}
/>) :
(<div className="header__navburger-close">
<img
className="header__close-icon"
alt="Close Menu"
src={closeicon}
onClick={() => props.handleCloseMenuClick()}
/>
<nav className="header__nav-list">
<Link to={`/home`} className="header__nav-link"
onClick={() => props.handleCloseMenuClick()}>Home</Link>
<Link to={`/resources`} className="header__nav-link"
onClick={() => props.handleCloseMenuClick()}>Patient Resources</Link>
<Link to={`/team`} className="header__nav-link"
onClick={() => props.handleCloseMenuClick()}>Meet the Team</Link>
<Link to={`/faq`} className="header__nav-link"
onClick={() => props.handleCloseMenuClick()}>FAQ</Link>
<Link to={`/fees`} className="header__nav-link"
onClick={() => props.handleCloseMenuClick()}>Fees</Link>
</nav>
</div>
)}
</div>
Did you mean icons of humburger menu changing slowly and glitchy? I've looked at the site and menu looks quite good for me.
First of all, there is no need in setState in your componentDidMount() as you should have the state set by this moment in constructor where initialization happens. This would force rendering the component twice with same state and be the reason that something works a little slow.
Second, do you use images for humburger menu icons? Downloading images takes some time as well, and I think that's why when clicking burger menu I don't see menu cross just in time. There are other ways to make menu like this, for exapmle it may be just
<div class="burger-menu">
<span></span>
</div>
and styles for span, span::before and ::after for white lines. You can also transform these lines to make a cross of it. I suggest this solution would allow things to work a little faster

Issue refreshing child components in React after implementing React DnD

I'm trying to implement a sortable list of sortable lists in React, using React DnD. Prior to implementing the drag and drop side of things, all was working well.
I have a container component, which renders this:
<DndProvider backend={Backend}>
{this.state.classifications.map((classification, index) =>
<Classification id={classification.id} classification={classification} reportTemplate={this} key={classification.id} index={index} />
)}
</DndProvider>
The Classification extends Component, constructed like this:
constructor(props) {
super(props);
this.state = {
isEditing: false,
classification: props.classification
};
}
... and renders this (condensed for brevity):
<div className="panel-body">
<DndProvider backend={Backend}>
{this.state.classification.labels.map((label, index) =>
<Label id={label.id} label={label} reportTemplate={this.props.reportTemplate} key={label.id} index={index} />
)}
</DndProvider>
</div>
In turn, the Label also extends component, constructed like this:
constructor(props) {
super(props);
this.state = {
isEditing: false,
label: props.label
};
}
... and renders like this (again condensed for brevity):
return (
<div className={"panel panel-default panel-label " + (isDragging ? "dragging " : "") + (isOver ? " over" : "")}>
<div className="panel-heading" role="tab" id={"label-" + this.state.label.id}>
<div className="panel-title">
<div className="row">
<div className="col-xs-6 label-details">
{this.state.isEditing
? <input type="text" className="form-control" value={this.state.label.value} onChange={e => this.props.reportTemplate.onLabelValueChange(e, this.state.label.classificationId, this.state.label.id, 'value')} />
: <p className="form-control-static">{this.state.label.value}</p>
}
<div className="subuser-container">...</div>
</div>
</div>
</div>
</div>
);
All of this works well - when the user makes a change from the Label child component, it gets updated in the root component and everything syncs up and refreshes.
However, when implementing React DnD, both the Classification and Label components have been wrapped in Drag and Drop decorators, to provide sorting. The sorting via drag and drop works perfectly. However: this has caused the updating of elements to stop working (i.e., when a change is made from the Label, the update is fed through to the root Component correctly, but it doesn't then refresh down the tree).
Both the classification and label dnd implementations are like this in the render method:
return connectDropTarget(connectDragSource(...));
... and this when exporting the component:
export default DropTarget('classification', classificationTarget, classificationDropCollect)(DragSource('classification', classificationSource, classificationDragCollect)(Classification));
Interestingly, when a label is edited, the refresh does then occur when the user drags and drops the component. So its like the drag and drop will trigger a component refresh, but not the other onChange functions.
That was a long question, apologies. I'm almost certain someone else will have experienced this issue, so any pointers gratefully appreciated.
Ok so i've basically answered my own question, but many thanks to those who posted comments on here to help narrow it down.
The answer was that my state object is complex and deep, and the component/decorator implementation of React DnD seems to have an issue with that. My assumption is that there is some behaviour in the decorator's shouldComponentUpdate that is blocking the components refresh when a deep property is update. React DnD's own documentation refers to the decorators as "legacy", which is fair enough.
I updated our components to use hooks instead of decorators, and it all sprang to life. So the answer is this, if your DnD implementation is deep and complex, use hooks.
Here is an example of your code without DnD that won't work either because the prop is copied to state in the constructor and on concurrent renders the prop is never used again, only the state.
In Child you can see that it will render but counter never changes, in CorrectChild the counter will change because it's just using props.counter.
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {//copied only once in constructor
counterFromParent: props.counter,
};
}
rendered=0;
render() {
this.rendered++;
return (
<div>
<h3>in broken Child rendered {this.rendered} times</h3>
<button onClick={this.props.up}>UP</button>
<pre>
{JSON.stringify(this.state, undefined, 2)}
</pre>
</div>
);
}
}
class CorrectChild extends React.Component {
render() {
//not copying props.count, just using it
return (
<div>
<h3>in correct Child</h3>
<button onClick={this.props.up}>UP</button>
<pre>
{JSON.stringify(this.props, undefined, 2)}
</pre>
</div>
);
}
}
function App() {
const [state, setState] = React.useState({ counter: 1 });
const up = React.useCallback(
() =>
setState((state) => ({
...state,
counter: state.counter + 1,
})),
[]
);
return (
<div>
<h3>state in App:</h3>
<pre>{JSON.stringify(state, undefined, 2)}</pre>
<Child counter={state.counter} up={up} />
<CorrectChild counter={state.counter} up={up} />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
If you still experience that without DnD your code "works" then please provide a Minimal, Reproducible Example of it "not working".

Advice on Component react-ratings-declaritive

I am using a component which I have downloaded from below:
https://www.npmjs.com/package/react-ratings-declarative
It works great, but I really need the functionality to disable the component in instances where I just want to display the rating, but not have the interactive element.
I have looked through the documentation and can't find anything to disable it directly. I can see some stuff on disabling inline styles, but not sure how this would work.
I have copied the raw HTML and tried to reconstruct a component with this functionality, but there seems to be so many styles to copy, I don't think this approach would work.
Can anyone advise if this is possible or recommend an alternative component which does this?
Just don't call the method that sets state. I used the example and got rid of the changeRating method and deleted the changeRating attribute. If there is no way to change the state, users can't update the ratings.
//IMPORT STATEMENTS ETC...
class Foo extends React.Component {
constructor(props) {
super(props)
this.state = { rating: 5 }
}
/* YOU DON'T NEED THIS METHOD EITHER IF YOU'RE NOT CHANGING STATE
changeRating(rating) {
this.setState({
rating: rating
})
}
*/
render() {
return (
<div>
<Ratings
/*changeRating={this.changeRating} <-- GET RID OF THIS LINE*/
rating={this.state.rating}
widgetRatedColors='blue'>
<Ratings.Widget />
<Ratings.Widget />
<Ratings.Widget
widgetDimension='60px'
svgIconViewBox='0 0 5 5'
svgIconPath='M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z'
/>
<Ratings.Widget widgetHoverColor='black' />
<Ratings.Widget />
</Ratings>
</div>
)
}
}
function App() {
return (
<div className='App'>
<main>
<Foo />
</main>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('example'))

How to build react component can change view type

I'm working a reactjs project have require to build a component can change view type. Like: the component have "view as icon" and "view as list", and have a button to switching eachother. Which the best way to archive that. Thanks
Edit: Sorry for making confuse
This is exactly what i want. As you can see, i have a mediaComponent and i want it can display in 2 different way: as a list and as thumbnail. So how can i do that with react. I don't actually have code for that.
p/s: I have tried conditional rendering but because it's different in render it's require to re-render the component with forceUpdate(). That's don't really look nice. So i hove there are another solution for that.
Render as thumbnail
Render as list
Something like that perhaps:
class MyComponent extends React.Component {
state = {
isList: false
}
toggleList = () => this.setState({ isList: !this.state.isList})
render(){
const { isList } = this.state;
return (
<div>
{isList ? <ListComponent /> : <GridComponent />}
<button onClick={this.toggleList}>Toggle</button>
</div>
)
}
}
export default MyComponent;

Resources