How to scroll to bottom of div - reactjs

I have troubles with scrolling down my component. I want scroll bar thumb to be at the very end of chat div from the start. I am not sure what the probleme is here. MessageTo and MessageFrom are components that represent paragraphs with text and display author's name. ChatInput is textarea with send button.
import React from 'react';
import './index.css';
import MessageFrom from './message-from';
import MessageTo from './message-to';
import ChatInput from './chat-input';
import SimpleBarReact from 'simplebar-react';
import 'simplebar/src/simplebar.css';
class Chat extends React.Component {
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate(){
this.scrollToBottom()
}
scrollToBottom = () => {
this.el.scrollIntoView({behavior:"smooth"});
}
render(){
return(
<div className="chat" id="slider-container">
<SimpleBarReact style={{maxHeight: 680}} id="scroll-bar-cont">
<div className="messages-container" id="for-slider" >
<MessageFrom />
<MessageTo />
<div style={{ float:"left", clear: "both" }}
ref={el => {this.el=el;}}>
</div>
</div>
</SimpleBarReact>
<ChatInput />
</div>
);
}
}
export default Chat;
https://codesandbox.io/s/great-currying-x4m8m?file=/src/message-to.js
It works well. But It doesn't work in next level component.

Related

Why does react display my functional component at the bottom of my page?

My main page looks like this :
import React from "react";
import { Fragment } from "react";
import ModalA from "../components/Modal/ModalOptionA";
export default class AePage extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Fragment>
<div className="grid-intro">
<div className="text-intro">
Some Text
</div>
<div className="modal-component-insert">
<ModalA show={true}/>
</div>
<div className="text-outro">
Some text
</div>
</div>
</Fragment>
)
}
}
And my component looks like this :
import React from "react";
import ReactDOM from "react-dom";
const Modal = ({ show, closed}) => {
return (
ReactDOM.createPortal(
<>
<div className="modal">
My Component
</div>
</>,
document.body
)
)
}
export default Modal;
The code above display something like :
Some Text
Some Text
My Component
Why does my component not display between the texts ? Is there a specific way for React to display this component between my divs ?
That is what ReactDOM.createPortal is for. It will always move things to the bottom of the DOM. That way, you can then position it above everything else using CSS.
It seems you don't really need that, so I'd just replace your code for the Modal component with:
import React from "react";
const Modal = ({ show, closed}) => {
return (
<div className="modal">
My Component
</div>
)
}
export default Modal;

React 16 - unable to make a modal render using createPortal

I'm trying to render a loading notification modal while a POST is processing.
It seems like it should be very simple using createPortal but the modal never displays.
I added a div in index with an id of modal:
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<div id="modal"></div>
</body>
Here is the react component. When the test button is clicked the state of showModal is set to true:
import React, { Component, Header } from 'react';
import { render } from "react-dom";
import { Row, Col, Button } from 'reactstrap'
import 'bootstrap/dist/css/bootstrap.css';
import ProcessingModal from '../Modals/ProcessingModal';
export class TestModal extends React.Component {
constructor(props) {
this.state = {
showModal: false,
}
this.handleShowModal = this.handleShowModal.bind(this);
}
handleShowModal() {
this.setState({ showModal: true });
}
render() {
return (
<div>
<div className='container-fluid'>
<h2 style={{ textAlign: 'center', border: 'none' }}>
Header Text
</h2>
<br />
{this.state.showModal ? <ProcessingModal /> : null }
<Row>
<Col md={6}>
<Button onClick={this.handleShowModal} type="button">test</Button>
</Col>
</Row>
</div>
</div>
);
}
This is the ProcessingModal js:
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
const ModalContent = (
<div className='modal text-center'>
<div className="spinner-border text-success"><br />
Loading...
</div>
</div>
);
function ProcessingModal(props) {
return ReactDOM.createPortal(ModalContent, document.querySelector("#modal"));
}
export default ProcessingModal;
Where am i going wrong?
I think first argument of createPortal expect a React Element, not React Component.
In ProcessingModal.js, wrap ModalContent into JSX Element:
return ReactDOM.createPortal(<ModalContent/>, document.querySelector("#modal"))
Styling was my issue. The modal style had display: none;
Once that was removed it worked.

withStyles component wrap

I have a following component:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import SnackbarContent from '#material-ui/core/SnackbarContent';
import Snackbar from '#material-ui/core/Snackbar';
const styles = theme => ({
error: {
backgroundColor: theme.palette.error.dark,
}
})
class Snack extends React.Component {
state = {
opendialog: false,
}
constructor(props) {
super(props);
}
test() {
this.setState({opendialog: !this.state.opendialog});
}
render() {
return (
<Snackbar open={this.state.opendialog}>
<SnackbarContent message="test"/>
</Snackbar>
);
}
}
export default withStyles(styles)(Snack);
and app main:
import React, { Component } from 'react';
import Button from '#material-ui/core/Button';
import logo from './logo.svg';
import './App.css';
import Snack from './Snack.js';
class App extends Component {
constructor(props) {
super(props);
this.snack = React.createRef();
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<Button variant="contained" color="primary" onClick={this.handleHello}>Hello World</Button>
<div>
<Snack ref={ ref => this.snack = ref } />
</div>
</div>
);
}
handleHello = () => {
this.snack.test();
}
}
export default App;
I get a "TypeError: _this.snack.test is not a function" when I click the button, however if I drop the withStyles the code works correctly.
I'm just replacing "export default withStyles(styles)(Snack);" line with "export default (Snack);".
Why it does not work correctly with the "withStyles"? How can I make it work?
Because withStyles wraps your component, you need to instead use:
<Snack innerRef={ref => (this.snack = ref)} />
withStyles passes the innerRef property to the wrapped component as ref.
I tried this using the latest version of #material-ui/core (currently 3.8.1). I can't guarantee that older versions support this in the same way.
Here's a fully working example:
The problem is because the withStyles HOC return a new component so you are getting the reference of the HOC. You can use innerRef prop:
<Snack innerRef={ ref => this.snack = ref } />
According to the official documentation:
It adds an innerRef property so you can get a reference to the wrapped component. The usage of innerRef is identical to ref.
You can check it in the official documentation here withStyle function.
I already tested it with your current version it works properly

ReactComponent Button value won't render on my react app

I've got a simple React App going on. My index.js file looks, of course, like this:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
Going deeper, my App.js file declares an App extends Compoennt class, which contains my to-be-rendered elements and their functions:
import React, { Component } from "react";
import logo from "./SmartTransit_logo.png";
import MyButton from "./components/MyButton";
import "./App.css";
import { isWallet, helloWorld } from "./services/neo-service";
class App extends Component {
state = {
inputValue: ""
};
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Smart Transit Live Demo</h1>
</header>
<div style={{ width: 500, margin: "auto", marginTop: 10 }}>
<MyButton
buttonText="My Button"
onClick={ params => {helloWorld();}}
/>
</div>
</div>
);
}
}
export default App;
And the declaration of MyButton from /components/MyButton:
import React, { Component } from "react";
import PropTypes from "prop-types";
class MyButton extends Component {
render() {
return (
<button className="MyButton"
value = {this.props.buttonText}
>
{this.props.children}
</button>
);
}
}
MyButton.propTypes = {
buttonText: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
};
export default MyButton;
Finally, the declaration for helloWorld() is done like so (NOTE: neon-js is an npm package I'm using):
import { wallet } from "#cityofzion/neon-js";
export function isWallet(address) {
console.log(wallet.isAddress(address));
return wallet.isAddress(address);
}
export function helloWorld() {
console.log("Hello world");
return 1;
}
My problem is that the resulting Button doesn't get its value text rendered, and although it gets the CSS code for it just fine, it appears empty!
Not only that, but pressing it doesn't log a "Hello World" in the console, as it should, so it's even disconnected from its onClick function.
Any idea on what I'm doing wrong?
Buttons don't receive a "value" prop. The text inside of the button element is what gives it its text.
The button does appear to accept children to use as button text, but no children is actually being passed down to it. this.props.children is the content between JSX tags when the component is rendered.
React doesn't add the event handlers to elements automatically. You have to pass them along yourself in order for them to be properly triggered.
With that in mind, here's how you should render your button in App:
<MyButton onClick={() => helloWorld()}>
My Button
</MyButton>
And here's how MyButton's code should look:
class MyButton extends Component {
render() {
return (
<button className="MyButton" onClick={this.props.onClick}>
{this.props.children}
</button>
)
}
}
As you can see, the buttonText prop is no longer required; that's what the children prop is for.
You need to define super(props) in class constructor when you are going to use this.props
constructor(props) {
super(props);
}
Define this in MyButton component.
The problem is, you are not calling onClick method from mybutton component and button take it's value between it's opening and closing tag.
Use this code:
this.props.onClick()}> {this.props.buttonText}

how to move a dragula draggable element to another div in react-dragula?

i'm having an issue with the react-dragula library https://github.com/bevacqua/react-dragula
i can create a column of draggable items but the items inside each column aren't exchangable with other columns, they can only be dragged inside their columns, so how can i make them draggable inside other columns ? (thanx in advance)
here's my code for the a column of draggable items
import React, {Component} from 'react';
import ProjectWidget from './ProjectWidget';
import Dragula from 'react-dragula';
class ProjectCol extends Component{
render(){
var dragulaDecorator = (componentBackingInstance) => {
if (componentBackingInstance) {
let options = { };
Dragula([componentBackingInstance], options);
}
};
return(
<div>
<div className="scrum_column_heading">To Do</div>
<div className="scrum_column">
<div id="scrum_column_todo" ref={dragulaDecorator} className="dragula dragula-vertical">
<ProjectWidget />
</div>
</div>
</div>
);
}
}
export default ProjectCol;
and here's the code for viewing multiple columns together
import React, {Component} from 'react';
import ProjectCol from './ProjectCol';
class ProjectList extends Component{
render(){
return (
<div class="scrum_board_overflow">
<div id="scrum_board" class="uk-clearfix">
<ProjectCol />
<ProjectCol />
<ProjectCol />
</div>
</div>
);
}
}
export default ProjectList;
Use only one Drake object on the ProjectList and push all DOM elements for the ProjectCol as containers in the used Drake.

Resources