I'm trying to solve kind of simple problem: when component is loaded, i need to scroll it to the bottom. But i've wasted ton of hours trying to solve it. I've tried a lot of different ways (scrollIntoView, scrollTop, scrollBy, etc...) but none of them can't do it. Url below is a link to fiddle where i have a simple component and i need Message to be shown. The problem is that i have to scroll about 10 pixels by myself. I would really appreciate if you help me to solve this problem.
class Hello extends React.Component {
componentDidMount() {
const elem = ReactDOM.findDOMNode(this.refs.test);
if (elem) {
elem.scrollIntoView(false);
}
}
render() {
return (
<div>
<div className="test"
ref="test">
Hello {this.props.name}
</div>
<div>Message</div>
</div>
)
}
}
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
JSFiddle
You placed the ref attribute on the wrong place.
Move it one level up in order to catch the whole component, including the "Message" text.
So, basically:
class Hello extends React.Component {
// ...
render() {
return (
<div ref="test">
<div className="test">
Hello {this.props.name}
</div>
<div>Message</div>
</div>
)
}
}
Here's a working jsfiddle demo, forked from yours.
class Hello extends React.Component {
// ...
componentDidUpdate() {
this.scrollDiv.scrollIntoView(false);
}
render() {
return (
<div
ref={(el) => {this.scrollDiv = el}}
>
<div className="test">
Hello {this.props.name}
</div>
<div>Message</div>
</div>
)
}
}
You should scroll only when the component is loaded into DOM filled with all props.
export default class Hello extends React.Component {
constructor(props,context){
super(props,context);
this.isAlreadyLoaded = false;
}
componentWillReceiveProps(nextProps) {
let scrollToElement = document.getElementById("scroll-element");
if (scrollToElement && !isAlreadyLoaded){
this.isAlreadyLoaded = true;
scrollToElement.scrollIntoView(true);
}
}
render(){
return {....}
}
}
Related
I want to get the text content of the react element. In the example below, I want get: hello 1
var node = <myComponent id={1} />
class myComponent extends React.Component {
render() {
return {
<span> hello {this.props.id} </span>
}
}
I tried to use node.text or ReactDOM.findDOMNode(node).textContent, but it doesn't work. Can I get some help?
Thanks!
Hi i think you should modify your code like below :
<myComponent id={1} />
Try calling your code using:
ReactDOM.render(<MyComponent id={1} />, document.getElementById("root"));
Your code:
class MyComponent extends React.Component {
render() {
return <span>Hello {this.props.id}</span>;
}
}
Link to this code in a Codesandbox:
https://codesandbox.io/s/class-component-dv6fj
i am making a website under react with reactstrap, i have a section that contains charts and a button whose function is to replace said charts with another chart containing more details. however i am struggling to make a concrete code.
i have tried placing the charts in a separate component and have it's content switch through the use of a handleclick function on the button that changes the state of the section (using 'onclick')
i am really not confident in my code's clarity, so i tried reproducing what i did in a simpler matter within fiddle
class hello extends React.Component {
render() {
return (
<h2>hello</h2>
);
}
}
class bye extends React.Component {
render() {
return (
<h2>goodbye</h2>
);
}
}
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<div>
<div>
{this.state.components[hello]}
</div>
<button onClick={this.handleClick}>
switch
{this.setState({components:[<bye />]})}
</button>
</div>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
the div in the "toggle" component is supposed to switch between the components "hello" and "bye"
in effect the current section that is supposed to be displayed ("hello") will be replaced by the other section ("bye") uppon clicking the button under them.
thanks in advance.
If you simply want to toggle between the two components with the button click, you can use conditional rendering.
Change your render method to this:
render(){
return (
<div>
{this.state.isToggleOn?<Hello />:<Bye />}
<button onClick={this.handleClick}>Switch</button>
</div>
}
Also keep your Component's name first character capitalized or react might complain. And using Class based Components is outdated. Hooks are the hot thing right now. So try to use more Functional Components.
Note: My answer assumes you are using babel presets for transpiling jsx and es6 syntax. If not, check out #Colin's answer. It also uses hooks.
why not import all partial views and conditionally render them based on the condition
{condition & <View1/>
There's a few mistakes in your code. Here's an example which does what you want using conditional rendering:
import React, { useState } from "react";
import ReactDOM from "react-dom";
const Hello = () => {
return <h2>hello</h2>;
};
const Bye = () => {
return <h2>bye</h2>;
};
const App = () => {
const [toggled, setToggled] = useState(true);
const handleClick = () => {
setToggled(!toggled);
};
const render = () => {
if (toggled) {
return <Hello />;
}
return <Bye />;
};
return (
<div>
<button onClick={handleClick}>toggle</button>
{render()}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
There are many ways to do it:
Using conditional operator:
{ this.state.isToggleOn?<Hello/>:<Bye/> }
Using if condition:
render() {
let chart;
if(this.state.isToggleOn) {
chart = <Hello/>;
} else {
chart = <Bye/>;
}
return ( <div> { chart } </div>);
}
3 You can use switch case also for conditional rendering. Here it is not well suited as condition is true or false.
I am building an App where Serverinput is being rendered.
Now I am trying to figure out, how it´s possible to display pure HTML. Because now it is only displayed as ...., where it should show an Image.
The question is, where should one call dangerouslySetInnerHTML() here to display all HTML as requested?
The Strings are being stores in an Array(messageList) that is being mapped. Userinput is escaped, so theres no problem on that side.
let listItems = messageList.map(d => (
<div >
<p className={d.senderId + "timestamp"}>{d.time}</p>
<p className={d.senderId} key={d.idCount} ref={d.idCount}>
{" "}
{d.text}{" "}
</p>
</div>
));
let gif1 = <img className="gif" alt="" src={gif} />;
return (
<div >
<div dangerouslySetInnerHTML={__html: {listItems}} />
<ul>{listItems}</ul>
</div>
);
Thanks a lot for any help that is given.
I updated the dangerousHTML where I thought it would work. But now it throws - Syntax error: Unexpected token, expected }
You shuould have something like this for each element that you want to show the dynamic content
<div dangerouslySetInnerHTML={__html: {yourHtmlContent}} />
How I understood is that Array(messageList) contains a list of markup strings.
So you just need to join them.
const messageList = [
"<h2>Header</h2>",
"<body>This is body!</body>",
"<footer>Footer!</footer>"
];
function createMarkup() {
return { __html: messageList.join("") };
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
It'd display something like this
You need to pass a string not an object as you do here.
(as it's just an implementation of innerHTML)
{__html: {listItems}}
Full source for completeness.
import React, { Component } from "react";
import { render } from "react-dom";
import "./styles.css";
const messageList = [
"<h2>Header</h2>",
"<body>This is body!</body>",
"<footer>Footer!</footer>"
];
function createMarkup() {
return { __html: messageList.join("") };
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
class App extends Component {
constructor() {
super();
this.state = {
name: "React"
};
}
render() {
return (
<div>
<MyComponent />
</div>
);
}
}
render(<App />, document.getElementById("root"));
Working demo.
I'm developing a more complex example of passing props from a component to another. In this case, it's the content of an array(when I click on that content) to a <div>.
You can find the code here: https://codesandbox.io/s/509j5npkwx
(Please check the code in the link above)
TextBox <div> component:
export class TextBox extends React.Component {
constructor(props) {
super(props);
this.state = {
content: "Select A Node To See Its Data Structure Here..."
};
this.changeContent = this.changeContent.bind(this);
}
changeContent(newContent) {
this.setState({
content: newContent
});
}
render() {
return (
<div className="padd_top">
<div className="content_box">{this.state.content}</div>
</div>
);
}
}
export default TextBox;
FileTree component:
export class FileTree extends React.Component {
constructor(props) {
super(props)
this.state = {
activeNode: null
}
this.setActiveNode = this.setActiveNode.bind(this)
}
setActiveNode(name) {
this.setState({ activeNode: name })
}
render() {
return (
<div className="padd_top">{
renderTree(
this.props.root || root,
this.setActiveNode,
this.state.activeNode
)
}
<TextBox />
</div>
)
}
}
I'm trying to do something like this, for further understanding: http://alexcurtis.github.io/react-treebeard/
I understood how to prepare the <div> to receive new information, by substituting the "Select A Node To See Its Data Structure Here..." when I click one of the elements belonging to the file tree.
I also understood how to prepare the file tree to pass content <div>, but in this case, I'm confused about where and how should I apply to the right component.
I'm new to React JS. If you have any tips for me about this issue, I'm very grateful.
Thank you.
I changed a bit the structure of my project, and now I'm looking forward to put <TextBox> and <FileTree> side by side.
More specifically, like this:
export class App extends React.Component {
render() {
return (
<div>
<div className="col-md-12">
<SearchEngine />
</div>
<div className="col-md-6">
<FileTree />
</div>
<div className="col-md-6">
<TextBox content={this.props.activeNode} />
</div>
</div>
);
}
}
I tought it wouldn't be different to pass props to <App>, but again I might be missing something, because it's not passing properly. What is missing here?
Thanks again.
I'm not sure if I understood your question.
Here is my fork: https://codesandbox.io/s/50pv75q8ll
Basically, you pass the activeNode to < TextBox />. Look at line 126 of index.js.
And then, in text_box.js use componentWillReceiveProps() to set the TextBox state with the content prop. Line 18 of text_box.js.
I have a react component, let's call him ReactContainer.
ReactContainer contains a few elements which one of them is MyReactBox and one of them is ReactInnerContainer (a code example is below).
My problem is that if a put an element inside ReactInnerContainer into fullscreen using the requestFullScreen API, then it overrides on MyReactBox, although MyReactBox has the CSS zIndex property to the maximum value possible.
export default class ReactContainer extends React.Component {
render() {
return (
<div>
<MyReactBox />
<br />
<ReactInnerContainer />
</div>
);
}
}
export default class ReactInnerContainer extends React.Component {
handleFullScreenClick() {
this.refs.innerDiv.webkitRequestFullscreen();
}
render() {
return (
<div ref="innerDiv">
/* Some stuff here */
</div>
);
}
}
I wish that although innerDiv is in fullscreen, MyReactBox will still be shown on the front of the screen. If I render MyReactBox inside innerDiv then it works, but I need MyReactBox to be rendered in ReactContainer.
Any ideas how to solve the problem?
Thanks a lot :)
Call webkitRequestFullscreen on the parent component
export default class ReactContainer extends React.Component {
handleFullScreen (){
this.screen.webkitRequestFullscreen();
}
render() {
return (
<div ref={(screen) => {this.screen = screen }}>
<MyReactBox />
<br />
<ReactInnerContainer handleFullScreen={this.handleFullScreen.bind(this)}/>
</div>
);
}
}
export default class ReactInnerContainer extends React.Component {
handleFullScreenClick() {
this.props.handleFullScreen();
}
render() {
return (
<div >
/* Some stuff here */
</div>
);
}
}