Updating a div size based on props in react - reactjs

I'm trying to implement a side nav bar like how it is shown on this website
https://adminlte.io/themes/AdminLTE/index2.html
Now I'm trying to basically emulate the expanded nav bar and mini navbar toggle. However, I'm having trouble updating the size of the navbar in react.
Here is my nav bar component
import React, { Component } from 'react';
class SideNavBar extends Component {
render() {
let sideBarStyle = {
'height': '100%',
'backgroundColor': 'lightblue',
'width': "80px",
'position': 'absolute',
'top': '0',
'left': '0'
}
setTimeout(() => {
sideBarStyle["width"] = "300px";
}, 1000)
return (
<div style={sideBarStyle}>
sidenavbar
</div>
);
}
}
export default SideNavBar;
I put a set timeout there just because I wanted to quickly test if it was possible to expand the div's width from a click event.
But I get the following error
TypeError: Cannot assign to read only property 'width' of object '#<Object>'
How do I go about updating an element's size based on click events?

Can you try below.
import React, { Component } from 'react';
class SideNavBar extends Component {
constructor(props){
super(props);
this.state = {
width : 80
}
}
componentDidMount(){
setTimeout(() => {
this.setState({
width: 300
})
}, 1000);
}
render() {
let sideBarStyle = {
'height': '100%',
'backgroundColor': 'lightblue',
'width': this.state.width,
'position': 'absolute',
'top': '0',
'left': '0'
}
return (
<div style={sideBarStyle}>
sidenavbar
</div>
);
}
}
export default SideNavBar;
One more thing you no need to specify px explicitly in React. Just no is enough. React will take care of px.

Related

Manage the reload of a component through another component located in a different route in REACT

I am having difficulties with my react application. I have a component that cyclically calls iframes, making them visible for a few seconds. The "reload" takes place via a button.
However, I need to check the iframe reload from another page. For example, create a "configuration.js" component in which there is a button which, once clicked, activates the "reload" function.
The iframe reload is however rendered in "http: // localhost: 3000 / simulatoretv", while the button that starts the reload is present in "http: // localhost: 3000 / configurator".
I hope I've been sufficiently clear. I attach the script of the component "Advertising", through which I run the reload of the iframes.
import React, { Component } from "react";
class Pubblicità extends Component {
state = {
index: 0,
iframeSrcs: ["/300x250", "/160x600", "/468x60"],
visibility: false
};
reload = () => {
const iframeLength = this.state.iframeSrcs.length;
if (this.state.index < iframeLength) {
this.setState({
index: this.state.index + 1,
visibility: true
});
} else {
this.setState({ index: 0, visibility: true }); //starting again
}
setTimeout(() => {
this.setState({ visibility: false });
}, 15000);
};
render() {
return (
<div>
<button
style={{
position: "absolute",
left: 0,
right: 0,
top: 500
}}
onClick={this.reload}
>
pubblicità
</button>
{this.state.visibility ? (
<iframe
style={{
position: "absolute",
left: 500,
right: 0,
top: 10
}}
key={this.state.index}
title="AdSlot"
src={this.state.iframeSrcs[this.state.index]}
height="100%"
width="100%"
scrolling="no"
frameborder="0"
/>
) : (
""
)}
</div>
);
}
}
export default Pubblicità;
This is the other component, where I would like the controlled iframes to be shown by the "Pubblicità" component.
The route of this component is "http: // localhost: 3000 / platformOTT".
import React, { Component } from "react";
import SimulatoreTV from "./SimulatoreTV";
import Pubblicità from "./Pubblicità";
class PiattaformaOTT extends Component {
render() {
return (
<div>
<SimulatoreTV />
<Pubblicità />
</div>
);
}
}
export default PiattaformaOTT;
Thanks to those who want to help me.

Openlayers Popup in React | How to?

Is there anyway to get popup overlay of OpenLayers working in react? I have no ideia how to get this working..
I've included a regular react openlayer overlay that stays over Viena on the map and a second overlay that pops up where ever a user clicks.
First install openlayers with npm i ol
Then create a class MapExample.js:
import React, { Component } from "react";
import ReactDOM from 'react-dom';
import Map from "ol/Map.js";
import View from "ol/View.js";
import Overlay from "ol/Overlay.js";
import LayerTile from "ol/layer/Tile.js";
import SourceOSM from "ol/source/OSM.js";
import * as proj from 'ol/proj';
import './MapExample.css';
const posViena = proj.fromLonLat([16.3725, 48.208889]);
export default class MapExample extends Component {
constructor(props) {
super(props);
this.state = { center: posViena, zoom: 3 };
this.map = new Map({
target: null, // set this in componentDidMount
layers: [
new LayerTile({
source: new SourceOSM()
})
],
view: new View({
center: this.state.center,
zoom: this.state.zoom
})
});
}
componentDidMount() {
this.map.setTarget("map");
// Listen to map changes
this.map.on("moveend", () => {
let center = this.map.getView().getCenter();
let zoom = this.map.getView().getZoom();
this.setState({ center, zoom });
});
// Basic overlay
const overlay = new Overlay({
position: posViena,
element: ReactDOM.findDOMNode(this).querySelector('#overlay'),
positioning: 'center-center',
stopEvent: false
});
this.map.addOverlay(overlay);
// Popup showing the position the user clicked
this.popup = new Overlay({
element: ReactDOM.findDOMNode(this).querySelector('#popup')
});
// Listener to add Popup overlay showing the position the user clicked
this.map.on('click', evt => {
this.popup.setPosition(evt.coordinate);
this.map.addOverlay(this.popup);
})
}
componentWillUnmount() {
this.map.setTarget(null);
}
render() {
return (
<div>
<div id="map" style={{ width: "100%", height: "360px" }}/>
<div className="blue-circle" id="overlay" title="overlay"/>
<div className="blue-circle" id="popup" title="Welcome to OpenLayers"/>
</div>
);
}
}
With a MapExample.css file like this:
.blue-circle {
width: 30px;
height: 30px;
border: 1px solid #088;
border-radius: 15px;
background-color: #0FF;
opacity: 0.5;
z-index: 9999; /* Watch out for this!!! */
}
Finally have your App.js like this:
import React from 'react';
import './App.css';
import MapExample from "./MapExample";
function App() {
return (
<div className="App">
<MapExample />
</div>
);
}
export default App;

react-custom-scrollbars jumps to top on any action

I am using react-custom-scrollbars in a react web app because I need to have two independant scroll bars, one for the main panel and one for the drawer panel. My issue is that the content in the main panel is dynamic and whenever I take some action in the main panel that changes state the scroll bar jumps to the top of the panel again.
UPDATE:
I believe I need to list for onUpdate and handle the scroll position there. If it has changed then update if not do not move the position?
In code, I have a HOC call withScrollbar as follows:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import AutoSizer from 'react-virtualized-auto-sizer';
import { Scrollbars } from 'react-custom-scrollbars';
import { colors } from '../../theme/vars';
import { themes } from '../../types';
// This is a Higher Order Component (HOC) used to
// provide a scroll bar to other components
export default (ChildComponent, styling) => {
class ComposedComponent extends Component {
state = {
// position: ??
};
handleUpdate = () => {
//update position
//this.scrollbar.scrollToBottom();
};
render() {
return (
<AutoSizer>
{
({ width, height }) => (
<Scrollbars
style={{ width, height, backgroundColor: colors.WHITE, overflow: 'hidden', ...styling }}
onUpdate={() => this.handleUpdate()}
renderThumbVertical={props => <Thumb {...props} />}
autoHide
autoHideTimeout={1000}
autoHideDuration={200}
>
<ChildComponent {...this.props} />
</Scrollbars>
)
}
</AutoSizer>
);
}
}
return ComposedComponent;
};
const Thumb = styled.div`
background-color: ${props =>
props.theme.theme === themes.LIGHT ? colors.BLACK : colors.WHITE};
border-radius: 4px;
`;
in my MainView component I just wrap the export like this:
export default withScrollbar(LanguageProvider(connect(mapStateToProps, null)(MainView)));
I have read a few similar issues on this like this one: How to set initial scrollTop value to and this one scrollTo event but I cannot figure out how to implement in my case. Any tips or suggestions are greatly appreciated.
So I found a way to get this to work and it feels like a complete hack but I'm posting in hopes it might help someone else.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import AutoSizer from 'react-virtualized-auto-sizer';
import { Scrollbars } from 'react-custom-scrollbars';
import { colors } from '../../theme/vars';
import { themes } from '../../types';
// This is a Higher Order Component (HOC) used to
// provide a scroll bar to other components
export default (ChildComponent, styling) => {
class ComposedComponent extends Component {
state = {
stateScrollTop: 0,
};
onScrollStart = () => {
if (this.props.childRef) { // need to pass in a ref from the child component
const { scrollTop } = this.props.childRef.current.getValues();
const deltaY = Math.abs(scrollTop - this.state.stateScrollTop);
if (deltaY > 100) { // 100 is arbitrary. It should not be a high value...
this.props.childRef.current.scrollTop(this.state.stateScrollTop);
}
}
};
handleUpdate = () => {
if (this.props.childRef) {
const { scrollTop } = this.props.childRef.current.getValues();
this.setState({ stateScrollTop: scrollTop });
}
};
render() {
return (
<AutoSizer>
{
({ width, height }) => (
<Scrollbars
ref={this.props.childRef}
style={{ width, height, backgroundColor: colors.WHITE, overflow: 'hidden', ...styling }}
onScrollStart={e => this.onScrollStart(e)}
onUpdate={e => this.handleUpdate(e)}
renderThumbVertical={props => <Thumb {...props} />}
autoHide
autoHideTimeout={1000}
autoHideDuration={200}
>
<ChildComponent {...this.props} />
</Scrollbars>
)
}
</AutoSizer>
);
}
}
return ComposedComponent;
};
const Thumb = styled.div`
background-color: ${props =>
props.theme.theme === themes.LIGHT ? colors.BLACK : colors.WHITE};
border-radius: 4px;
`;
I use this HOC like this:
create a ref for the component you want to use it with
pass the ref to the component that will use the HOC:
class SomeChildComponent extends Component {
...
viewRef = React.createRef();
...
render() {
return ( <MainView childRef={this.viewRef} />)
}
import and wrap the component
import withScrollbar from '../../hoc/withScrollbar';
...
export default withScrollbar(MainView);
I tried the above solution and it didn't seem to work for me.
However what did work was making sure that my child components inside Scrollbars were wrapped in a div with a height of 100%:
<Scrollbars>
<div style={{ height: '100%' }}>
<ChildComponent />
<ChildComponent />
</div>
</Scrollbars>

Embed Typeform in React app

How can I embed a Typeform form in my React app?
The embed code that Typeform provide doesn't compile in JSX.
This is a sample of the embed code:
<div class="typeform-widget" data-url="https://sample.typeform.com/to/32423" style="width: 100%; height: 500px;"></div> <script> (function() { var qs,js,q,s,d=document, gi=d.getElementById, ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm", b="https://embed.typeform.com/"; if(!gi.call(d,id)) { js=ce.call(d,"script"); js.id=id; js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })() </script> <div style="font-family: Sans-Serif;font-size: 12px;color: #999;opacity: 0.5; padding-top: 5px;"> powered by Typeform </div>
You can use a React wrapper component I created: https://github.com/alexgarces/react-typeform-embed
It uses the official Typeform Embed SDK under the hood. Basically you have to pass your form url, but it also supports other SDK options.
import React from 'react';
import { ReactTypeformEmbed } from 'react-typeform-embed';
class App extends React.Component {
render() {
return <ReactTypeformEmbed url="https://demo.typeform.com/to/njdbt5" />;
}
}
You can view Typeform documentation for embedding with JavaScript here.
And their official npm module here.
Use React refs to trigger initialisation similarly to how you would initialise a jQuery plugin for instance.
import React from 'react';
import * as typeformEmbed from '#typeform/embed'
class Form extends React.Component {
constructor(props) {
super(props);
this.el = null;
}
componentDidMount() {
if (this.el) {
typeformEmbed.makeWidget(this.el, "https://sample.typeform.com/to/32423", {
hideFooter: true,
hideHeaders: true,
opacity: 0
});
}
}
render() {
return (
<div ref={(el) => this.el = el} style={{width: '100%', height: '300px'}} />
)
}
}
export default Form;
Inspired by Elise Chant's solution and using function based components, hooks and Typescript, this is what I come up with for my project. I did not want to install another thin wrapper on top of the official SDK.
import * as typeformEmbed from '#typeform/embed';
import React, { useEffect, useRef } from 'react';
interface EmbeddedTypeformProps {
link: string;
hideFooter?: boolean;
hideHeaders?: boolean;
opacity?: number;
}
export const EmbeddedTypeform: React.FunctionComponent<EmbeddedTypeformProps> = ({
link,
hideFooter = true,
hideHeaders = true,
opacity = 90,
}) => {
const elementRef = useRef(null);
useEffect(() => {
typeformEmbed.makeWidget(elementRef.current, link, {
hideFooter,
hideHeaders,
opacity,
});
}, [link]);
return (
<div
ref={elementRef}
style={{ width: '100%', height: '100%', flex: '1 1 auto' }}
/>
);
};
If you are using Typescript with react and you got this error just make sure that noImplicitAny set to false in tsconfig file :
"noImplicitAny": false,

How to call a component function on other component, but from the other component ? React

Currentl, I am doing a React project. I want to ask:
lets say there are 3 components, A,B, and C.
A is my container, B is the input one, and C is the output one.
this is my component A :
import React, { Component } from 'react';
import './App.css';
import {SubmitComponent} from './submitComponent.js'
// import {OutputCo} from './TopicsContainer.js'
const containerStyle = {
border: '2px solid black',
width: '70%',
height: 'auto',
marginLeft: 'auto',
marginRight: 'auto',
marginBottom: '100px',
};
class App extends Component {
render() {
return (
<div style={containerStyle}>
<h1 style={{textAlign:'center'}}>Coding Exercise</h1>
<hr />
<SubmitComponent />
<OutputComponent />
</div>
);
}
}
export default App
Component B is SubmitComponent, component C is OutputComponent, my B is taking the input and save it as its state :
import React, { Component } from 'react';
import React, { Component } from 'react';
const createstyleouter ={
border : '2px solid #AAA',
width : '98%',
height: 'auto',
marginLeft: 'auto',
marginRight: 'auto',
marginTop:'35px',
marginBottom:'50px',
};
const createstyleinner ={
// border: '2px solid blue',
marginLeft: 'auto',
marginRight: 'auto',
marginTop: '10px',
width: '98%',
}
export class SubmitComponent extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
desc: ''
}
this.newTitle = this.newTitle.bind(this);
this.newDesc = this.newDesc.bind(this);
}
newTitle(e) {
this.setState({
title: e.target.value
});
}
newDesc(e) {
this.setState({
desc: e.target.value
});
}
render() {
return (
<div style={createstyleouter}>
<div style={createstyleinner}>
<p><strong>Title:</strong></p>
<textarea style={{width:'100%', height:'20', fontSize:'17px'}} onChange={this.newTitle} maxLength='150' value={this.state.title} placeholder="Enter your topic's title"></textarea>
<p>Description:</p>
<textarea style={{width:'100%', height:'70', fontSize:'17px'}} onChange={this.newDesc} maxLength='150' value={this.state.desc} placeholder="Enter your topic's description'"></textarea>
<button style={{padding: '10px', marginBottom:'10px'}}>Submit</button>
</div>
</div>
);
}
}
I literally did not have any idea how to send this state to C so C can post is as the topic,
Please help
If you wish to call method from other components, you have to pass method around as props.
class Parent extends Component {
render() {
return (
// pass method as props to Child component
<Child parentMethod={this.parentMethod}/>
);
}
parentMethod() {
console.log('Hello World');
}
}
class Child extends Component {
render() {
return (
<button onClick={this.handleClick}>Fire parent method</button>
);
}
handleClick() {
// parent method passed to child is now available as props
// you can call it now & even pass arguments if you like
this.props.parentMethod('foo', 'bar', 2, ['foo', 'bar'], {foo: 'bar'});
}
}
If passing around methods gets tricky (e.g one component wants to call a method of component that is in a totally different place in your component tree), you could consider context.
But be warned - read the docs I linked, it makes your code harder to understand and get into.
In the constructor of the parent:
this.childElement = React.createRef();
In your child element in the parent:
<Child ref = {this.childElement}>
To call a method of the child use:
this.childElement.current.aFunctionInChildClass();
For more information in react documentation/refs and the dom
You need to lift the state up so state is passed as props from container to child components.
Let us say you have a structure
class A
{
getResponse:function(res)
{
set you state//
this.setState({
state:res
})
}
<B state={this.state} callback={this.getResponse}/>
<C state={this.state} />//state is the updated state by function callback
}
in Component B you need to call function callback as
class B
{
callAComponent:function(res)
{
this.props.callback(res)
}
render{
return(
<input type="text" onChange={this.callAComponent}//whaever event you are performing
)
}
}
Now send the update state in C component

Resources