Custom Read More in React.js - reactjs

As you can see this image, "+Las mor" is a "see more" button, which when clicked expands the whole paragraph written above.
I need React code for this to be functional. Any help will be appreciated.
I am also attaching the code upon which this functionality is to be applied.
<section id="section-2">
<h4>Om mig</h4>
<p className="para">
{about}
</p>
</section>
<p style={{color:'#d39176'}}>
<img src={plus1} />
Läs mer
</p>

You probably want a button that toggles the state of expanded text onClick. Upon hitting the button you would set the state to the opposite of what it was. Here's a working example I wrote with React and Reactstrap. I just tested it locally. Here's a video demo of what you will see: https://screencast.com/t/in5clDiyEcUs
import React, { Component } from 'react'
import { Container, Button } from 'reactstrap'
class App extends Component {
constructor(props) {
super(props)
this.state = {
expanded: false //begin with box closed
}
}
//function that takes in expanded and makes it the opposite of what it currently is
showButton = () => {
this.setState({ expanded: !this.state.expanded })
}
render() {
const { expanded } = this.state
return (
<Container style={ { justifyContent: 'center', alignItems: 'center' } }>
<div>Always visable text.</div>
<Button onClick={ this.showButton }>Expand</Button>
{
expanded && //show if expanded is true
<div>Extended Text Here</div>
}
</Container>
)
}
}
export default App

Related

Why I can't use an imported component inside a functional component in React?

I am new to React. For the code readability, instead of in-line styled button, I want to write it as a separate class component. I created a customed button 'addImageButton'and imported it to another .js file. It doesn't render the customer button when I try to use it within a functional component. How can I make the functional component be able to use the imported button? Thanks!
//addImageButton.js
import React, { Component } from "react";
class addImageButton extends Component {
render() {
return (
<div>
<button
style={{
borderStyle: "dotted",
borderRadius: 1,
}}
>
<span>Add Image</span>
<span>Optional</span>
</button>
</div>
);
}
}
export default addImageButton;
//AddNewTaskButton.js
import React, { Component } from "react";
import Modal from "react-modal";
**import addImageButton from "../addImageButton";**
class AddNewTaskButton extends Component {
constructor(props) {
super(props);
this.state = {
show: false,
};
this.setShow = this.setShow.bind(this);
this.closeShow = this.closeShow.bind(this);
this.addTaskModal = this.addTaskModal.bind(this);
}
setShow() {
this.setState({
show: true,
});
}
closeShow() {
this.setState({
show: false,
});
}
addTaskModal = () => {
return (
<div>
<Modal
isOpen={this.state.show}
onRequestClose={() => this.closeShow()}
>
**<addImageButton />**
</Modal>
</div>
);
};
render() {
return (
<div>
<button onClick={() => this.setShow()}>
<img src={addIcon} alt={text}></img>;
<span>text</span>
</button>
<this.addTaskModal className="modal" />
</div>
);
}
}
export default AddNewTaskButton;
Easier way would be to just use functional components. Also, react components should be upper case, like so:
export default function AddImageButton() {
return (
<div>...</div>
)
}
create a different component for Modal
import Modal from './Modal'
import AddImageButton from './AddImageButton'
function AddTaskModal() {
return (
<div>
<Modal> <AddImageButton/> </Modal>
</div>
)
}
then
import AddTaskModal from './AddTaskModal'
function AddNewTaskButton() {
return (
<div>
<AddTaskModal/>
</div>
)
}
I don't know your file directories, so I just put randomly.
as for your question, try to make the AddImageButton as a class and see if it renders then. If it doesn't it might be due to something else. Do you get errors? Also maybe create the AddTaskModal class separately and render it out as a component. Maybe that'll help

Display element based on event fired and props passed in

I am trying, to manipulate another element, by, passing props directly to it, and then have it display itself. If I pass true/false.
Live running code:
https://codesandbox.io/s/keen-dan-rt0kj
I don't know if it's possible to have a system of objects, and based on an event, tell a parent to display a child.
App.js
import React from "react";
import "./styles.css";
import Content from "./components/Content";
export default class App extends React.Component {
state = {
display: false
};
render() {
return (
<div className="App">
<button onClick={() => this.setState({ display: !this.state.display })}>
Display div
</button>
<Content display={this.state.display} />
</div>
);
}
}
./components/Content.js:
import React from "react";
export default class Content extends React.Component {
constructor(props) {
super();
this.state = {
display: props.display
};
}
render() {
const { display } = this.state;
return (
<div
id="mydiv"
className="mydiv"
style={{ display: display ? "block" : "none" }}
>
<h3>A simple div</h3>
</div>
);
}
}
Goal:
I want to based on a state, and based on fired event, display an element that already in store of root.
EDIT: I am aware that, this exists and can be used: import PropTypes from 'prop-types', however, I am not sure this is good practice, since it requires some parent or some other component to implement the props.
JUST Tried:
App:
<Content display={this.state.display} content={"Hello World"} />
Content:
<h3>{this.state.content}</h3>
It seems the passed in text, stored in Content state = {content: props.content} does get displayed, wheres, the boolean value does not work directly. Is there something wrong with sending in a bool ?
try this in your Content Component
export default class Content extends React.Component {
constructor(props) {
super();
this.state = {
};
}
render() {
return (
<>
{this.props.display?(
<div
id="mydiv"
className="mydiv"
>
<h3>A simple div</h3>
</div>
):null}
</>
);
}
}
The reason this may not be working is because you are initiating the state in a way that does not connect the display props after the component is initialized. This means that after the Content component is "constructed", the state of the Content and it's parent are not linked. This is because the constructor() function is only run once to initialize the state.
The best option you have is to not use the internal state of the Content component. Rather than initializing state with the display prop, just use the display prop in your render function.
Trying something like this might work
import React from "react";
export default class Content extends React.Component {
constructor(props) {
super(props);
}
render() {
const { display } = this.props;
return (
<div
id="mydiv"
className="mydiv"
style={{ display: display ? "block" : "none" }}
>
<h3>A simple div</h3>
</div>
);
}
}
Also I would reccommend using state in the root:
import React from "react";
import "./styles.css";
import Content from "./components/Content";
export default class App extends React.Component {
constructor(props) {
super();
state = {
display: false
};
}
render() {
return (
<div className="App">
<button onClick={() => this.setState({ display: !this.state.display })}>
Display div
</button>
<Content display={this.state.display} />
</div>
);
}
}

Unable to make react-player light prop always true

I have implemented a slider like property. Inside each slide, there is a video and its name. I am using [react-player][1] to display the video thumbnail. Once you click on any of the video a modal will get open and will play the video I have rendered the react-player is that the light property is always true. But it's not working once you click on the video that particular position of the slider loses the light property.
import React, { Component } from 'react'
import IndividualSlider from './IndividualSlider'
import ModalVideo from 'react-modal-video'
import { Modal, Button } from 'antd';
import ReactPlayer from 'react-player/youtube';
export class Experience extends Component {
constructor(){
super();
this.state={
Video:[
{
url:'https://www.youtube.com/embed/H2yCdBIpxGY',
name:'Recurssion'
},
{
url:'https://www.youtube.com/embed/s5YgyJcoUI4',
name:'Array'
},
{
url:'https://www.youtube.com/embed/_C4kMqEkGM0',
name:'DP'
},
{
url:'https://www.youtube.com/embed/VBnbYNksWTA',
name:'Graph'
},
{
url:'https://www.youtube.com/embed/M1q3Pzk2UXs',
name:'Trie'
}
],
modalIsOpen:false,
modalLink:""
}
this.left = this.left.bind(this);
this.right=this.right.bind(this);
this.modalPlay = this.modalPlay.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.handleOk = this.handleOk.bind(this);
}
handleOk = e => {
console.log(e);
this.setState({
modalIsOpen: false,
});
};
handleCancel = e => {
console.log(e);
this.setState({
modalIsOpen: false,
});
};
modalPlay=(link)=>{
this.setState({
modalIsOpen:true,
modalLink:link
})
}
right=()=>{
let arr = this.state.Video;
let temp = arr[0];
arr.shift();
arr.push(temp);
this.setState({
Video:arr
})
}
left=()=>{
let arr = this.state.Video;
let temp = arr[arr.length-1];
arr.pop();
arr.unshift(temp);
this.setState({
Video:arr
})
}
render() {
return (
<div className="ExperienceAClass">
<div className="OneWeekHeading">
<h2 className="OneWeekCaption">
Experience a class
</h2>
<hr className="MentorsCaptionUnderLine" align="center" width="50%"></hr>
</div>
<Modal
title=""
visible={this.state.modalIsOpen}
onOk={this.handleOk}
onCancel={this.handleCancel}
footer={null}
>
<ReactPlayer className="ModalVideo" url={this.state.modalLink}/>
</Modal>
<div className="EntireSliderWrapper">
<a class="prev" onClick={this.left}>
</a>
<div className="VideoSlider">
{this.state.Video.map((child,index)=>{
return <IndividualSlider modalPlay={this.modalPlay} url={child.url} name=
{child.name}/>
})
}
</div>
<a class="next" onClick={this.right}>
</a>
</div>
</div>
)
}
}
export default Experience
And the IndividualSlider component is as follows:
import React, { Component } from 'react'
import ReactPlayer from 'react-player/youtube';
export class IndividualSlider extends Component {
constructor(){
super();
this.state={
light:true
}
this.onClick=this.onClick.bind(this)
}
onClick=()=>{
let modalPlay=this.props.modalPlay;
modalPlay(this.props.url);
}
render() {
return (
<div className="VideoDetails fade">
<ReactPlayer className="YoutubeVideo" onClick={this.onClick} light =
{this.state.light} url={this.props.url}/>
<p>
{this.props.name}
</p>
</div>
)
}
}
export default IndividualSlider
In the above code, I have made the light prop to be always true. As the slide is clicked this component renders but the thumbnail property is not held.
Also, When the modal closes the video keeps on playing. How to deal with that?
As you can see the video which was played regain it's light={true} once slid but the position where it was when played doesn't imply light={true}
I believe the problem is that because you have two instances of React player, one has the light property passed to it and the other is not. Since you always want the light property to work, pass it as a prop set to true always.
The light property is working in the individual slider, because you are indeed setting it in the individual slider
// Inside IndividualSlider component you have this
<ReactPlayer className="YoutubeVideo" onClick={this.onClick} light =
{this.state.light} url={this.props.url}/>
// remove state it and make it like this, since state is not needed
<ReactPlayer className="YoutubeVideo" onClick={this.onClick} light={true} url={this.props.url}/>
Now you are losing the light when clicking on an individual video, because that video is rendered in the parent component (the Experience component_, and there you are not passing the light prop
// In Experience Component you have this
<ReactPlayer className="ModalVideo" url={this.state.modalLink} />
// change it to
<ReactPlayer className="ModalVideo" url={this.state.modalLink} light={true} />

In React JS, how do I tell a parent component that something has happened in the child?

I have a React JS app with a simple hierarchy: ContainingBox wraps two InfoBox components. in this example, I simply want to tell the ContainingBox component 1) that something has been clicked, and 2) which InfoBox (by label name) has been clicked?
Here is some basic code that works in my browser to get this question up & running. All it does it console.log when you click onto one of the InfoBox elements on the page.
Essentially, what I am trying to achieve is that I want the ContainingBox to change state (specifically, border color as rendered) when one of the child InfoBox elements is clicked.
I'm not sure what the right direction here is.
I built this app with React 16.10.2, but I would be happy to read answers pointing me towards the latest 'React way' of thinking.
import React from 'react';
import styled from 'styled-components'
import './App.css';
const StyledInfoBox = styled.div`
width: 100px;
border: solid 1px green;
padding: 10px;
cursor: pointer;
`
class InfoBox extends React.Component {
constructor({blurb}) {
super()
this.state = {
label: (blurb ? blurb.label : ""),
}
this.selectBox = this.selectBox.bind(this);
}
selectBox(e) {
e.preventDefault()
console.log("selectBox")
// how do I tell the ContainingBox component 1) that something has been clicked,
// and 2) which InfoBox (by label name) has been clicked?
}
render() {
const {label} = this.state
return (
<StyledInfoBox onClick={this.selectBox} >
{label}
</StyledInfoBox>
)
}
}
class ContainingBox extends React.Component {
render() {
return (
<div>
<InfoBox key={1} blurb={{label: "Aenean malesuada lorem"}} />
<InfoBox key={2} blurb={{label: "Lorem Ipsum dor ameet"}} />
</div>
)
}
}
function App() {
return (
<div className="App">
<ContainingBox />
</div>
)
}
export default App;
You pass a callback from the parent component to child component via the props.
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
changeNameTo = (newName) => this.setState({name: newName})
render() {
return (
<div>
<h1>{this.state.name}</h1>
<p>
<Child callbackExample={this.changeNameTo} />
</p>
</div>
);
}
}
Then you have your Child component.
class Child extends Component {
render() {
return(
<div>
<button onClick={() => this.props.callbackExample("Doggos")}>
Click me
</button>
</div>)
}
}
When you click the button, the callback is invoked setting the state of the parent, which is then reflected when the parent re-renders.

React Native : Regarding State and Callback handlers

So I am still learning React Native and I am trying to build a very simple app to understand state, events in React Native.
Here in this app I display a button titled "first" as soon as the app is rendered on the screen.
Upon clicking that button a modal is displayed. This modal contains a button titled "second".
The objective is to hide the modal upon "onPress" of the "second" button.
Thsi is my code.
import React from 'react';
import { StyleSheet, Text, View, Button, Modal } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.showModal = this.showModal.bind(this);
}
state = {
modalVisible: false,
}
hideModal = () => {
console.log("Btnpress pressed");
this.setState({modalVisbile: false});
}
showModal() {
console.log("BtnPress1 pressed");
this.setState({modalVisible: true});
}
render() {
return (
<View style={styles.container}>
<Button title="first"
onPress={this.showModal}
disabled={this.state.modalVisible} />
<Modal
animationType= "slide"
transparent= {false}
visible={this.state.modalVisible}
>
<Button
title="second"
onPress={this.hideModal}
disabled={!this.state.modalVisible}
/>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
What Happens
a) There are no errors.
b) The app is rendered successfully and display the button "first".
c) When the "first" button is clicked, the second button("second") contained in the modal is rendered as expected.
d) But when the "second" button is clicked the "first" button is not rendered.
My understanding is that upon "onPress" event on "second" button the below callback is invoked which changes the state.
onPress={this.hideModal}
After changing that state (which would now be modalVisible = false) the button titled "first" will be rendered. But this is not happening.
Can some one tell em what I am doing wrong ?
In your code, you misspelled visible, if you correct the spelling, it looks like it will work
hideModal = () => {
console.log("Btnpress pressed");
this.setState({modalVisible: false}); /*you had modalVisbile*/
}

Resources