Fade transition not working on React Bootstrap Alert component - reactjs

I have an alert which I display every time I load a page and the user can close the alert when ever he wants.
Now I want to add a closing transition to the alert but it doesn't seem to work.
I've tried a lot of things but still no transition effect on my alert.
Here is my code now:
function ReactTip(props){
if(props.display){
return(
<Bs.Fade in={props.display}>
<div>
<Bs.Alert variant={props.variant} onClose={props.onClose} dismissible>
<FaLightbulb /> Tip: For multiple inputs, you can press tab while inside a text box to automatically add a new row.
</Bs.Alert>
</div>
</Bs.Fade>
);
}
return null;
}
Note that the value of props.display is true. What is wrong with my code?
Update #1:
I tried this and the transition is working but the div is still there like the CSS display is set to hidden and not none.
return(
<Bs.Fade in={props.display}>
<div>
<Bs.Alert variant={props.variant} onClose={props.onClose} dismissible>
<FaLightbulb /> Tip: For multiple inputs, you can press tab while inside a text box to automatically add a new row.
</Bs.Alert>
</div>
</Bs.Fade>
);

I can't find a way to make the <Fade /> work so I just used <Collapse />
Here is my updated code:
<Bs.Collapse in={props.display}>
<div>
<Bs.Alert variant={props.variant} onClose={props.onClose} dismissible>
<FaLightbulb /> Tip: For multiple inputs, you can press tab while inside a text box to automatically add a new row.
</Bs.Alert>
</div>
</Bs.Collapse>

Use the transition prop transition={Fade}.

Related

React widgets combobox; how to clear input or prevent selection

I'm using the combobox from React Widgets as a search UI component.
I've put in a custom render item so that when you click a search result in the dropdown, you navigate to the relevant page.
However when you select a result, the name of the selected item goes into the text input, which isn't what a user will expect when they select a search result. I think they'd expect the search term to remain, or perhaps the input to be cleared.
I like the Combobox component and haven't found another UI widget that would do what I want, so I'd like to find a solution.
Is there some way to override the selection behaviour so that clicking a list item doesn't select it? I've tried setting the 'onSelect' property but this doesn't suppress the default selection behaviour, it just adds extra functionality.
Alternatively is there a way to manually set the selection to null? The docs don't seem to show anything. I tried getting the input node's value manually to '' with reactDOM, but the value didn't change. I would guess that the component controls it.
I've wrapped the Combobox in a functional component:
function Search(props) {
...
const onSelect = (value) => {
const node = ReactDOM.findDOMNode(Search._combobox);
const input = node.getElementsByTagName('input')[0];
input.value = '';
}
return (
<Combobox
ref={(c) => Search._combobox = c}
onSelect={onSelect}
textField="name"
valueField="_id"
/>
);
}
If I set the value prop of the Combobox then it is impossible to type into it.
Any suggestions? Thank you.
The solution I found is to create my own search controls using an input and a button, and hide the native input and button with display: none. "componentDidUpdate" detects when new search results arrive and opens the dropdown to show them.
There is a manually-added 'show more...' entry at the end of search results. Clicking this increases the search limit for that group. That's the main reason I wanted to avoid showing the clicked result in the text input. The custom input is not affected by the user's selection, it always shows the search term.
My search component now looks something like this:
<div className="search">
<div className="search-controls">
<Input
onChange={this.onChangeInput}
type="text"
/>
<Button
onClick={this.toggleOpen}
title="toggle results"
>
<FontAwesomeIcon icon={['fas', 'search']} style={{ 'color': iconColors.default }} size="1x" />
</Button>
</div>
<Combobox
busy={isSearching}
data={searchResults}
onChange={() => {}}
open={open}
onSelect={this.onSelect}
textField="name"
valueField="_id"
/>
</div>

Rendering link within a Modal from reactstrap library

I'm rendering a Modal from reactstrap library, and i want to have within this text modal another link tag. Something like "Click here to show it". So, when the modal appears, the user can see that text and also can click on the here word to render another different Modal. How can achieve that?
This is my code:
code where i'm calling the Modal
<Modal
show={showGeneralModal}
children={"Click " + here + " to show it"}
title={modalTitle}
size={modalSize}
onExit={this.toggleNormalModal}
/>
code from the original exported Modal
return (
<div>
<Modal
isOpen={isOpen}
backdrop="static"
keyboard={false}
toggle={this.toggle}
size={size}
onExit={onExit}
>
<ModalHeader className={modalHeaderClasses} toggle={this.toggle}>
{title}
</ModalHeader>
<ModalBody className={modalBodyClasses}>
{children}
</ModalBody>
</Modal>
</div>
);
I'm getting right now this text within the modal:
Click [object Object] to show it
And i would like to have instead
Click here to show it
and when i click on here word, the other Modal should be rendered.
Any suggestions?
I can't modify the original Modal code cause it is being used for many other components in different places.
Btw, i was in a wrong way to do that. If you are in the same trouble, you may know that children is an already prop of react which allows you to access whatever you passed in the component that you are accessing to.
Knowing that, you don't have to pass children prop, just pass within the component whatever you want to be inside of children prop. So, instead of doing this:
<Modal
show={showGeneralModal}
children={"Click " + here + " to show it"}
title={modalTitle}
size={modalSize}
onExit={this.toggleNormalModal}
/>
do this:
<Modal
show={showGeneralModal}
title={modalTitle}
size={modalSize}
onExit={this.toggleNormalModal}
> Click here to show it
</Modal>

Semantic UI React side bar render pusher only on visibility change (redux/rematch)

I am using react and semantic. I am using the multiple sidebar example. The idea is that the left hand sidebar offers up some menu options, and then the right hand sidebar is the sub menu based on which option from the left menu is chosen. When a sub menu item is selected, a component is added to the Sidebar.Pusher, i.e displayed on the page.
It all works except re-rendering the content of the Sidebar.Pusher. This apparently only updates when the left hand side bar's visibility changes. I am using redux/rematch to handle state, and can see that the state that holds the content of the Sidebar.Pusher is being updated, but `render() is only being called when visibility changes of the sidebar.
The content of Sidebar.Pusher is an array, and I even tried displaying on the page the length of the array, which is being updated (pushed into) each time an item on the right hand sidebar is clicked. However this doesn't cause a render() to be fired, its literally when the left hand sidebar visibility changes.
Just to note, I did see this issue, however its from last year, and the answer wasn't enough for me to be able to fix the issue. Help would be appreciated.
Structure:
Index.js renders App.js, App.js renders Menu.js (which is a semantic set of tabs). One of the menu options is Sidebar.js which renders:
<Sidebar.Pushable as={Segment}>
<Sidebar
as={Menu}
animation="overlay"
direction="right"
inverted
vertical
visible={secondaryVisibility}
width="wide"
>
{focusedList.map((el, i) => {
return (
<Menu.Item key={i} as="a" onClick={() => this.addSegment(el)}>
<Article el={el} />
</Menu.Item>
)
})}
</Sidebar>
<Sidebar
as={Menu}
animation="overlay"
icon="labeled"
inverted
// onHide={this.handleSidebarHide}
vertical
visible={primaryVisibility}
width="wide"
>
<Menu.Item
onClick={() => this.changeTab(menuItem)}
as="a"
name="menuItem"
header
>
Menu Item
</Menu.Item>
</Sidebar>
<Sidebar.Pusher style={{ minHeight: "600px" }}>
<Segment basic>
{segments.map((el, i) => {
console.log(`el ${el}`)
return <Content key={i} segment={el} />
})}
</Segment>
</Sidebar.Pusher>
and all state (secondaryVisibility etc) is stored in rematch
Thanks
I haven't been able to identify the problem based on the code you've posted, could you provide more info such as the entire Sidebar.js and maybe what's in the Content component?. My guess would be that there's a HOC or lifecycle method getting in the way.
I've created a trivial example that seems to work fine, if I understand what you're trying to accomplish: https://codesandbox.io/s/myl6xpz9py
I got it. I forgot about immutability in state. Perhaps someone will benefit from this.
I was trying to update a state array with
let tmp = prevState.contract.segments
tmp.push(segment)
this.update({ segments: tmp })
However, this won't work as tmp is a reference to prevState.contract.segments, so this won't work, as pushing to tmp is equivelent to pushing to prevState.contract.segments.
you have to have a completely new array:
const tmp = [...prevState.contract.segments, segment]
this.update({ segments: tmp })
Now it works.

Dynamic Popover in ReactJS

I'm fairly new to React and I'm using the Ant Design framework (https://ant.design/).
I have a table list of items that I'm looking to have a button on each so that when it is pressed additional information about that row becomes available (which is a secondary API call specific to that row).
I'm trying to use a popover but I'm noticing that the popover wants the text before being rendered which is a problem since I don't have that information until the second API call. The best idea I've come up so far is to have the button press trigger the api call and then the state is updated but that creates a funky experience (as it is update after the popover is already opened - after starting with the previous rows information). It isn't a huge amount of time but it still isn't an ideal experience.
This is what I have so far:
<Popover content={this.contentSec([record['section']])} title=
{record['section']} trigger="click">
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
</Popover>
this.sectionAttributes triggers my fetch request. and this.contentSec does the formatting on the existing popup (see below).
contentSec(props) {
const listItems = this.state.attributes.map((item) =>
<li>{item}</li>
);
return <div><ul>{listItems}</ul></div>
}
Any ideas of a better way to handle this so that there isn't that buggy delay when clicking the button for the popover?
Thanks.
As the content is populated after the second api call, You can send two props content which can be empty string or any default value and loading variable as true on click. Once you have the data after the API call you can send the updated props ie content with actual text and loading as false and finally handle your logic and state update in componentwillrecieveprops() in the popover component.
You can use the loading prop to switch from a loader initially to the actual content.
Write a condition to check if the response from this.sectionAttributes(record['section'] is true, if it is true then
<Popover content={this.contentSec([record['section']])} title=
{record['section']} trigger="click">
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
</Popover>
else simply use
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
For the first time user clicks on button, the component rerenders and state gets updated, so when it rerenders you can see popover as the if condition satisfy.

How to replace a component with another one upon event (button click) in react js

I have a long list of data display divided into blocks with an edit button on side of each block, like this:
Whenever the edit button is clicked, i need to replace the display component with edit component, replacing the text with form like this
what would be the best way to do this.
I have tried putting the components inside state as list and replacing Display component with Form Component, when Edit is clicked
so instead of returning this from render():
return(
<Display />
);
Now i am returning:
return(
{this.state.components[0]}
);
and when button is clicked doing this
this.setState({components:[<EditForm />]})
It works but i was wondering is storing Component and JSX inside state a good idea/ professional practice?
you could do something like this:
use a variable in state for knowing edit is clicked or not
state={
isEdit:false,
}
on click of edit:
this.setState({isEdit:true})
in render() use conditional rendering:
render(){
return(
<div>
{(!this.state.isEdit) ? <Display /> : <EditForm />}
</div>
)
}
I would hold in state just a Boolean for showing the edit form or the display and toggle this on button click.
Then in you render method just a simple if statement to choose what to render e.g.
render() {
if (this.state.edit) return <EditForm />
return <Display />
}

Resources