React boostrap carousel not working as expected - reactjs

I am basically trying to fetch results of upcoming movies from the IMDB API into my react app, and display it as a carousel. The API is working fine, and I am getting the data as expected, but it is getting displayed one below another on my page, and not as a carousel
The code:
const UpcomingMovie = () => {
const [upcomingMovies, setUpcomingMovies] = useState([])
const fetchData = () => {
Axios.get(upcoming_movies_url).then((res) => {
setUpcomingMovies(res.data.results.slice(0, 10));
console.log(res.data.results)
}).catch(err => console.log(err))
}
useEffect(() => {
fetchData()
}, [])
return <div style={{ display: 'block', width: "90%", padding: "20px", margin: "auto" }}>
<Carousel className="carousel-upcoming" variant="dark">
{upcomingMovies.length > 0 &&
upcomingMovies.map((latmovies) => <Carousel.Item key={latmovies.id} {...latmovies} style={{ display: "flex" }}>
<img className="d-block w-100" src={"https://image.tmdb.org/t/p/w1280" + latmovies.poster_path} style={{ width: "200px", float: "right", padding:"20px" }} alt="First slide" />
<Carousel.Caption style={{ paddingLeft: "10px" }}>
<h3>{latmovies.title} ({latmovies.release_date.slice(0,4)})</h3>
<h6 style={{ margin: "0px" }}>Overview</h6>
<p style={{ fontSize: "12px", marginTop: "0px" }}>{latmovies.overview}</p>
</Carousel.Caption>
</Carousel.Item>)
}
</Carousel>
</div>
};
export default UpcomingMovie;
I am using this for my carousel. Any help is greatly appreciated!

Related

component re-render after every request, usememo not working

I am getting a list of tasks from API, every request fetch 15 tasks, when I click on the task it shows me a modal popup, and the data in that modal blinks when the next request hits, and it re-renders the entire page. I want not to blink data in the modal which are already fetched. data in modal comes from the form.io
I also tried several react/usememo solutions like
Widget.js
return (
<div className="dashboard_widget_card box-shadow p-3 card draggable dropzone ui-droppable " style={{ wordWrap: 'anywhere', fontSize: '14px', color: 'grey', borderRadius: '20px' }} >
<h4 style={{
fontsize: '15px',
color: ' #585858',
fontweight: '500',
}}>My Tasks</h4>
{DataCombines.map((element) => {
const datetype = moment(element.estimated_completion_date).format(
"DD-MM-YYYY"
);
if (datetype === tomorrow) {
globalvariable = "Tomorrow";
} else if (datetype === today) {
globalvariable = "Today";
} else {
globalvariable = "Other";
}
return (
<div style={{ marginRight: '20px' }}>
{DataCombines ?
<Card taskdata={element} taskTime={globalvariable} feths={FetchAll} /> :
<Backdrop
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
>
<CircularProgress color="inherit" />
</Backdrop>
}
</div>
);
})}
</div>);
Card.js
<div onClick={handleClickOpen} key={taskdata._id} >
<p
style={{
textTransform: "capitalize",
wordwrap: " anywhere",
fontSize: "14px",
fontWeight: "600",
color: "#313332",
}}
>
{taskdata.task_title}
</p>

How to use MessageBird SMS with a form in React?

When I use MessageBird with a phone number that was hardcoded, everything goes well. The message is sent correctly and I am satisfied.
The problem is when I try to send an SMS with a form where the user needs to enter the phone number.
I am using React Hooks.
function Account() {
const { authenticate, isAuthenticated, account, chainId, logout } =
useMoralis();
const [isModalVisible, setIsModalVisible] = useState(false);
const [isAuthModalVisible, setIsAuthModalVisible] = useState(false);
const [phoneNumber, setPhoneNumber] = useState();
function phoneNumberFromForm (phone) {
setPhoneNumber (phone);
console.log(" phone: ", phoneNumber);
}
if (!isAuthenticated || !account) {
return (
<>
<div onClick={() => setIsAuthModalVisible(true)}>
<p style={styles.text}>Authenticate</p>
</div>
<Modal
visible={isAuthModalVisible}
footer={null}
onCancel={() => setIsAuthModalVisible(false)}
bodyStyle={{
padding: "15px",
fontSize: "17px",
fontWeight: "500",
}}
style={{ fontSize: "16px", fontWeight: "500" }}
width="340px"
>
<div
style={{
padding: "10px",
display: "flex",
justifyContent: "center",
fontWeight: "700",
fontSize: "20px",
}}
>
Connect Wallet
</div>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
{connectors.map(({ title, icon, connectorId }, key) => (
<div
style={styles.connector}
key={key}
onClick={async () => {
try {
if (connectorId) {
await authenticate({ provider: connectorId });
window.localStorage.setItem("connectorId", connectorId);
} else {
await authenticate();
}
setIsAuthModalVisible(false);
} catch (e) {
console.error(e);
}
}}
>
<img src={icon} alt={title} style={styles.icon} />
<Text style={{ fontSize: "14px" }}>{title}</Text>
</div>
))}
</div>
</Modal>
</>
);
}
return (
<>
<div style={styles.account} onClick={() => setIsModalVisible(true)}>
<p style={{ marginRight: "5px", ...styles.text }}>
{getEllipsisTxt(account, 6)}
</p>
<Blockie currentWallet scale={3} />
</div>
<Modal
visible={isModalVisible}
footer={null}
onCancel={() => setIsModalVisible(false)}
bodyStyle={{
padding: "15px",
fontSize: "17px",
fontWeight: "500",
}}
style={{ fontSize: "16px", fontWeight: "500" }}
width="400px"
>
Account
<Card
style={{
marginTop: "10px",
borderRadius: "1rem",
}}
bodyStyle={{ padding: "15px" }}
>
<Address
avatar="left"
size={6}
copyable
style={{ fontSize: "20px" }}
/>
<div style={{ marginTop: "10px", padding: "0 10px" }}>
<a
href={`${getExplorer(chainId)}/address/${account}`}
target="_blank"
rel="noreferrer"
>
<SelectOutlined style={{ marginRight: "5px" }} />
View on Explorer
</a>
</div>
<div>
<PhoneInput enableAreaCodeStretch onChange={phone => phoneNumberFromForm({phone})}/>
</div>
<Button
size="small"
type="primary"
style={{
width: "50%",
marginTop: "10px",
borderRadius: "0.5rem",
fontSize: "12px",
fontWeight: "500",
}}
onClick={async () => {
console.log(" phone number on form", phoneNumber);
messagebird.messages.create({
originator : '67528923',
recipients : '$phoneNumber.phone',
body : 'testing this function. '
},
function (err, response) {
if (err) {
console.log("ERROR:");
console.log(err);
} else {
console.log("SUCCESS:");
console.log(response);
}
});
}}
>
Verify phone number
</Button>
</Card>
<Button
size="large"
type="primary"
style={{
width: "100%",
marginTop: "10px",
borderRadius: "0.5rem",
fontSize: "16px",
fontWeight: "500",
}}
onClick={async () => {
await logout();
window.localStorage.removeItem("connectorId");
setIsModalVisible(false);
}}
>
Disconnect Wallet
</Button>
</Modal>
</>
);
}
export default Account;
Can anyone tell me what I am doing wrong?
This is the error I am getting.
Error: api error(s): no (correct) recipients found (code: 9, parameter: recipient)
I believe it must have something to do to how I am calling the recipient's number.
I am using this line.
recipients : '$phoneNumber.phone',
I am using the code above, but is it the correct way to call that object?
You guessed it right, the problem is in the place where you call MessageBird API.
messagebird.messages.create({
originator : '67528923',
recipients : '$phoneNumber.phone',
body : 'testing this function. '
},
recipients should be array of strings (phone numbers), e.g.:
{
'originator': 'YourBrand',
'recipients': [
'31612345678'
],
'body': 'Hello, world!'
}
So I think in your code you need to change it to:
messagebird.messages.create({
originator : '67528923',
recipients : [phoneNumber.phone],
body : 'testing this function. '
},

Creating Tweet Display Box in ReactJS

I am using the following code to generate a Tweet input box which takes in text/video/image/emoji. And they can be in different combinations.
I am not sure how to generate a tweet display box which shows the final display containing text/image/emoji ? I understand I might need to put the different inputs in an array or some sort but what after that. My current code for display side is performing nothing and I am not sure where to go from here.
I am looking for display box to be of following form after a Submit Button:
Code components/EmojiPicker.js has:
import React, {useState} from 'react'
import ReactDOM from "react-dom";
import { Picker } from "emoji-mart";
import Button from "#material-ui/core/Button";
const EmojiPicker = ({ onSelect }) => {
const [show, setShow] = useState(false);
return (
<>
<Button
onClick={() => setShow(oldState => !oldState)}
style={{ width: "30px", height: "30px", borderRadius: "4px", border: "3px solid", display: "flex", alignItems: "center", justifyContent: "center",
background: "transparent"}}>
ej
</Button>
{ReactDOM.createPortal(
show && <Picker onSelect={onSelect} />,
document.body
)}
</>
);
};
export default EmojiPicker
Code components/FileInput.js has:
import React, {useRef} from 'react'
const FileInput = ({ onChange, children }) => {
const fileRef = useRef();
const onPickFile = event => {
onChange([...event.target.files]);
};
return (
<div
style={{
width: "35px",
height: "35px",
borderRadius: "3px"
}}
onClick={() => fileRef.current.click()}
>
{children}
<input
multiple
ref={fileRef}
onChange={onPickFile}
type="file"
style={{ visibility: "hidden" }}
/>
</div>
);
};
export default FileInput
Code components/tweetboxImgInp.js as:
import React, {useState, useEffect} from 'react'
const ImgIcon = () => (
<svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M14 13l4 5H6l4-4 1.79 1.78L14 13zm-6.01-2.99A2 2 0 0 0 8 6a2 2 0 0 0-.01 4.01zM22 5v14a3 3 0 0 1-3 2.99H5c-1.64 0-3-1.36-3-3V5c0-1.64 1.36-3 3-3h14c1.65 0 3 1.36 3 3zm-2.01 0a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h7v-.01h7a1 1 0 0 0 1-1V5z" />
</svg>
);
export const Img = ({ file, onRemove, index }) => {
const [fileUrl, setFileUrl] = useState(null);
useEffect(() => {
if (file) {
setFileUrl(URL.createObjectURL(file));
}
}, [file]);
return fileUrl ? (
<div style={{ position: "relative", maxWidth: "230px", maxHeight: "95px" }}>
<img
style={{
display: "block",
maxWidth: "230px",
maxHeight: "95px",
width: "auto",
height: "auto"
}}
alt="pic"
src={fileUrl}
/>
<div
onClick={() => onRemove(index)}
style={{
position: "absolute",
right: 0,
top: 0,
width: "20px",
height: "20px",
borderRadius: "50%",
background: "black",
color: "white",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
x
</div>
</div>
) : null;
};
export default ImgIcon
And App.js has:
import React, { useRef, useState } from "react";
import ImgIcon, {Img} from './components/tweetboxImgInp'
import EmojiPicker from './components/EmojiPicker'
import FileInput from './components/FileInput'
import "emoji-mart/css/emoji-mart.css";
import "./styles.css";
function App() {
const [text, setText] = useState("");
const [pics, setPics] = useState([]);
const textAreaRef = useRef();
const insertAtPos = value => {
const { current: taRef } = textAreaRef;
let startPos = taRef.selectionStart;
let endPos = taRef.selectionEnd;
taRef.value =
taRef.value.substring(0, startPos) +
value.native +
taRef.value.substring(endPos, taRef.value.length);
};
return (
<div style={{display: "flex", flexDirection: "column", border: "3px solid", borderRadius: "5px", width: "600px", minHeight: "200px", padding: "20px"}} >
<div style={{ display: "flex", flexDirection: "column", flex: 1, border: "1px solid", borderRadius: "5px", margin: "0px"}}>
<textarea
ref={textAreaRef}
value={text}
style={{ flex: 1, border: "none", minHeight: "150px" }}
onChange={e => setText(e.target.value)}
/>
<div style={{ display: "flex", flexDirection: "row", flexWrap: "wrap", background: "fbfbfb"}} >
{pics.map((picFile, index) => (
<Img key={index} index={index} file={picFile} onRemove={rmIndx =>
setPics(pics.filter((pic, index) => index !== rmIndx))}/>))}
</div>
</div>
<div style={{ display: "flex", flexDirection: "row", alignItems: "center", marginTop: "20px" }}>
<div style={{ marginRight: "20px" }}>
<FileInput onChange={pics => setPics(pics)}>
{/* <ImgIcon /> */}
Tes
</FileInput>
</div>
<EmojiPicker onSelect={insertAtPos} />
</div>
</div>
);
}
export default App
Edit: I am good with the display box accepting only 1 media file, text and few emoji. It will surprise me if I am the only one in 2019 looking to do it for fun.
Working Example
Click the codesandbox button to view the demo
The tweet display component is pretty straightforward. Its a flexbox column with two parts. First part of the column contains the tweet. The second part of the column contains the list of images/media elements. Emoji is part of the text component.
Tweet Display Component
const Tweet = ({ tweet: { text, images } }) => (
<div
style={{
margin: "20px",
border: "1px solid grey",
width: "600px",
padding: "20px",
borderRadius: "3px"
}}
>
<div>{text}</div>
{images.length > 0 && (
<div
style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
background: "fbfbfb",
padding: "30px 0"
}}
>
{images.map((img, i) => (
<Img key={i} file={img} index={i} isSingle={images.length === 1} />
))}
</div>
)}
</div>
);
For more info checkout this css-tricks article to get more info on css flex layout

Building Twitter Like Dialogbox for input

I am learning ReactJS and Material-UI and hence I have been working to build a semi twitter clone.
I am now hitting a road block in the sense that I can't figure how to build this input dialog box which can take all of text, video, photo, gif in same box.
Using <Input /> I can provide individually what kind of input I have i.e. email, password, etc using type. But I am not sure how to design this particular dialog box to take multiple inputs.
Can you please show me a working code example ?
Its 2019 and a lot of things have changed. This is a very rough and hacky implementation of how twitter has implemented. Its pretty simple.
Working Demo Link
For folks who want to just look at the code head over to codesandbox
Note: this was done very quickly to demonstrate what twitter has done under the hood.
The editor mainly consists of a <textarea /> where text for the tweets are added.
Below the text area is an expanding div block which loops image files that are selected from file system.
As for the emoji, a standard emoji picker is used to select emojis and plain old javascript is used to add emojis at the current cursor position in the textarea.
I have skipped the gif picker, as its similar to the image picker, the only difference being, a modal is open to populate gifs from giphy. An api from giphy. can be easily integrated to achieve this.
The following are the components written
FileInput Component
The FileInput component is used as the button and file picker to select images. Its a plain <input type="file" />. The native styles are hidden and a custom icon is displayed
const FileInput = ({ onChange, children }) => {
const fileRef = useRef();
const onPickFile = event => {
onChange([...event.target.files]);
};
return (
<div
style={{
width: "35px",
height: "35px",
borderRadius: "3px"
}}
onClick={() => fileRef.current.click()}
>
{children}
<input
multiple
ref={fileRef}
onChange={onPickFile}
type="file"
style={{ visibility: "hidden" }}
/>
</div>
);
};
Img Component
The Img component displays the images selected from the input. It uses URL.createObjectURL to create a temporary local url that can be populated inside an img tag. This is the image preview seen in the tweet sheet below the textarea.
const Img = ({ file, onRemove, index }) => {
const [fileUrl, setFileUrl] = useState(null);
useEffect(() => {
if (file) {
setFileUrl(URL.createObjectURL(file));
}
}, [file]);
return fileUrl ? (
<div style={{ position: "relative", maxWidth: "230px", maxHeight: "95px" }}>
<img
style={{
display: "block",
maxWidth: "230px",
maxHeight: "95px",
width: "auto",
height: "auto"
}}
alt="pic"
src={fileUrl}
/>
<div
onClick={() => onRemove(index)}
style={{
position: "absolute",
right: 0,
top: 0,
width: "20px",
height: "20px",
borderRadius: "50%",
background: "black",
color: "white",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
x
</div>
</div>
) : null;
};
App (Tweet Sheet)
This is the root component that stitches everything together.
function App() {
const [text, setText] = useState("");
const [pics, setPics] = useState([]);
const textAreaRef = useRef();
const insertAtPos = value => {
const { current: taRef } = textAreaRef;
let startPos = taRef.selectionStart;
let endPos = taRef.selectionEnd;
taRef.value =
taRef.value.substring(0, startPos) +
value.native +
taRef.value.substring(endPos, taRef.value.length);
};
return (
<div
style={{
display: "flex",
flexDirection: "column",
border: "3px solid",
borderRadius: "5px",
width: "600px",
minHeight: "200px",
padding: "20px"
}}
>
<div
style={{
display: "flex",
flexDirection: "column",
flex: 1,
border: "1px solid",
borderRadius: "5px",
margin: "0px"
}}
>
<textarea
ref={textAreaRef}
value={text}
style={{ flex: 1, border: "none", minHeight: "150px" }}
onChange={e => setText(e.target.value)}
/>
<div
style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
background: "fbfbfb"
}}
>
{pics.map((picFile, index) => (
<Img
key={index}
index={index}
file={picFile}
onRemove={rmIndx =>
setPics(pics.filter((pic, index) => index !== rmIndx))
}
/>
))}
</div>
</div>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
marginTop: "20px"
}}
>
<div style={{ marginRight: "20px" }}>
<FileInput onChange={pics => setPics(pics)}>
<ImgIcon />
</FileInput>
</div>
<EmojiPicker onSelect={insertAtPos} />
</div>
</div>
);
}
EmojiPickerModal
const EmojiPicker = ({ onSelect }) => {
const [show, setShow] = useState(false);
return (
<>
<button
onClick={() => setShow(oldState => !oldState)}
style={{
width: "30px",
height: "30px",
borderRadius: "4px",
border: "3px solid",
display: "flex",
alignItems: "center",
justifyContent: "center",
background: "transparent"
}}
>
ej
</button>
{ReactDOM.createPortal(
show && <Picker onSelect={onSelect} />,
document.body
)}
</>
);
};
Note: For the emoji picker a popular open source emoji picker component emoji-mart was used

Speeding up react Component rendering

I have a react component that renders fine but as soon as i add images it renders far slower and causes a few hundred miliseconds delay on the component rendering. Does anyone know a way to speed this up or what I am doing wrong?
class SearchResults extends React.Component {
render() {
//Individual container styling
const divStyle = {
float: 'left',
width: '80px',
height: '80px',
border: '5px solid pink',
borderRadius: '3px',
margin: '2px',
cursor: 'pointer',
backgroundColor: 'white'
};
const styleImage = {
maxWidth: '70px',
maxHeight: '70px',
margin: 'auto',
display: 'flex'
}
//Individual record
const startItem = (this.props.itemsPerPage * this.props.page) - this.props.itemsPerPage;//First item on page
const endItem = startItem + this.props.itemsPerPage;
//Slice is from/to
const all = searchableDatabase.slice(startItem, endItem).map((value, index) => {
return (
<div style={divStyle} >
{value.edit_title_normal}
{/*<img style={styleImage} src={'YourMemories/' + currentCollection.id + '/' + value.sequentialNumber + '/' + value.sequentialNumber + ' Thumbnail.jpg'} />*/}
</div>
)
});
//Main container
return (
<div>
<div style={{ clear: 'both', paddingTop: '20px', paddingBottom: '20px', textAlign: 'center' }}>
<Pagination allLength={searchableDatabase.length} page={this.props.page} itemsPerPage={this.props.itemsPerPage} />
</div>
<div>
{all}
</div>
</div>
);
}
}

Resources