How to use MessageBird SMS with a form in React? - reactjs

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. '
},

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>

Data filter with map, shows for 1/2 second then goes blank

On my test branch I can get this to work just fine, but when I try to add it to my partners work, it will map just fine but when I add the .filter with the following line .includes(query.toLowerCase()) like below, The page will load for 1/2 a second and then instantly go blank. I get an error in the console saying:
"Uncaught TypeError: query.toLowerCase is not a function"
< BasicModal />
<input
autoFocus={true}
onChange={event => setQuery(event.target.value)} placeholder="Search...">
</input>
</div>
<br />
<hr />
<div>
{
wikiData.filter(data =>{
if(query === ''){
return data;
} else if (data.title.toLowerCase().includes(query.toLowerCase())) {
return data;
} else if (data.body.toLowerCase().includes(query.toLowerCase())) {
return data;
}
}).map((data, index) => (
<div key={data.id}
ref={refs[data.id]}
style={{ height: 'flex', paddingLeft: '5%', paddingRight: '5%' }}>
<h1 style={{ fontSize: 24, fontWeight: "bold", textAlign: "center" }}>{data.title}</h1>
<div style={{ textAlign: "center", paddingBottom: "10px", Top: "-5px!important" }}>
<Tooltip title="Edit Content">
<EditIcon data-id={data.id} fontSize='large' color='action' style={{ paddingRight: "10px", cursor: "pointer" }} onClick={() => handleEdit(data, index)} />
</Tooltip>
<Tooltip title="Save Edit">
<Check data-id={data.id} fontSize='large' color='success' style={{ paddingRight: "10px", cursor: "pointer" }} onClick={() => saveEdit(data, index)} />
</Tooltip>
<Tooltip title="Delete Post">
<CloseIcon fontSize='large' color='error' style={{ cursor: "pointer" }} />
</Tooltip>
</div>
<div id={data.id} className="wiki-unedited" onChange={handleChange} value={data.body} >{data.body}</div>
<hr style={{ paddingLeft: "10%", paddingRight: "10%", width: "80%" }} />
</div>
))}
</div>
</Grid>
</Grid>
</div>
I figured it out... I didnt post it all to make it solvable either.. I had the state variable set to an array instead of a string...

React doesn't render array [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 1 year ago.
my React code doesn't works.
I've an array, and, for each item, I need to render a card.
But it doesn't works.
This is all the code:
const Home: NextPage = () => {
const [servers, setServers] = useState({});
async function getServers() {
console.log('ready');
const response = await fetch('http://localhost:3000/server/servers').then(
(res) => res.json()
);
setServers(response);
console.log(response);
console.log('servers object updated: ' + JSON.stringify(servers));
}
useEffect(() => {
getServers();
import('bootstrap/dist/js/bootstrap');
WebFont.load({
google: {
families: ['Karla:600', 'sans-serif'],
},
});
}, []);
useEffect(() => {
console.log('servers object updated: ' + JSON.stringify(servers));
}, [servers]);
return (
<div className="app">
<div className="container">
<div className="row" style={{ color: 'white' }}>
{servers.database?.map((server, index) => (
<div key={index} className="col">
<div
className="card"
style={{
width: '18rem',
backgroundColor: '#101114',
color: 'white',
marginTop: '80px',
borderRadius: '15px',
boxShadow: '4px 3px 5px 0px #7335fb',
}}
>
<img
src="https://cdn.discordapp.com/icons/843104500713127946/a_91371d39bec9e454d0f4ccacbfaea9f8.gif?size=512"
className="card-img-top"
alt="Icona server"
style={{
borderRadius: '50%',
width: '96px',
marginLeft: '20px',
marginTop: '60px',
}}
/>
<div className="card-body">
<h5 className="card-title">
{servers.bot[index].name || 'Errore!'}
</h5>
<br />
<p className="card-text">{server.shortDescription}</p>
<br />
<a
href="#"
className="btn"
style={{ backgroundColor: '#5316d9', color: 'white' }}
>
Entra
</a>
<a
href="#"
className="btn"
style={{
marginLeft: '10px',
backgroundColor: '#5316d9',
color: 'white',
}}
>
Visita
</a>
<br />
</div>
</div>
</div>
))}
</div>
</div>
</div>
);
};
export default Home;
The problem is here:
servers.database?.map((server, index) => (
<div key={index} className="col">
<div
className="card"
style={{
width: '18rem',
backgroundColor: '#101114',
color: 'white',
marginTop: '80px',
borderRadius: '15px',
boxShadow: '4px 3px 5px 0px #7335fb',
}}
>
<img
src="https://cdn.discordapp.com/icons/843104500713127946/a_91371d39bec9e454d0f4ccacbfaea9f8.gif?size=512"
className="card-img-top"
alt="Icona server"
style={{
borderRadius: '50%',
width: '96px',
marginLeft: '20px',
marginTop: '60px',
}}
/>
<div className="card-body">
<h5 className="card-title">{servers.bot[index].name || 'Errore!'}</h5>
<br />
<p className="card-text">{server.shortDescription}</p>
<br />
<a
href="#"
className="btn"
style={{ backgroundColor: '#5316d9', color: 'white' }}
>
Entra
</a>
<a
href="#"
className="btn"
style={{
marginLeft: '10px',
backgroundColor: '#5316d9',
color: 'white',
}}
>
Visita
</a>
<br />
</div>
</div>
</div>
));
Here the console output:
Someone know why it doesn't works?
No error, all works fine, but he doesn't load array.
VScode tell me that the initial useState value doesn't contain necessary data, but it arrive from database after, so I don't care.
If you have any suggestion/solution, please tell me.
Thanks in advance and sorry for bad English!
If you check your console.log("servers object updated: " + JSON.stringify(servers)); log you'll see that it's an object without a database property.
From what I can see of the logged state, the render should use the servers.servers property array to map:
{servers.servers?.map((server, index) => (
<div key={index} className="col">
<div className="card" style={{ width: "18rem", backgroundColor: "#101114", color: "white", marginTop: "80px", borderRadius: "15px", boxShadow: "4px 3px 5px 0px #7335fb" }}>
<img src="https://cdn.discordapp.com/icons/843104500713127946/a_91371d39bec9e454d0f4ccacbfaea9f8.gif?size=512" className="card-img-top" alt="Icona server" style={{ borderRadius: "50%", width: "96px", marginLeft: "20px", marginTop: "60px" }} />
<div className="card-body">
<h5 className="card-title">{servers.bot[index].name || "Errore!"}</h5><br />
<p className="card-text">{server.shortDescription}</p><br />
<a href="#" className="btn" style={{ backgroundColor: "#5316d9", color: "white" }}>Entra</a>
<a href="#" className="btn" style={{ marginLeft: "10px", backgroundColor: "#5316d9", color: "white" }}>Visita</a>
<br />
</div>
</div>
</div>
))}

passing value of form input to function onSubmit

I need to pass the value of the form input (inside render property of the "nextNode" object) to a
handler function on submission. Any ideas?
const nextNode = {
id: `node-${schema.nodes.length + 1}`,
content: `Node ${schema.nodes.length + 1}`,
coordinates: [
desiredcoordinates[0],
desiredcoordinates[1],
],
parent: null,
level: 2,
form: null,
className:'button blue',
render: ({id,form}) => (
<div id={id} style={{ fontSize: '0.5rem', textAlign: 'left', padding: '4px', width: '70px', height: '40px' }} onClick={() => toggleSelect(id)}>
<a>
<form style={{ display: form? 'none' : 'block' }}>
<label>Form: </label><input style={{ width: '25px', height: '12px' }} type='text'></input>
<button type="submit" className='buttonInputSubmit'>+</button>
</form>
<div style={{ display: form? 'block' : 'none' }}> Form: {form}</div>
<div>
</div>
</a>
</div>
)
,
};
Instead of handling on submission your input should be connected to a state and always be updating that state. Submission should not be used to set in values.
<const nextNode = {
const [input, setInput] = useState("")
function handleChange(e){
setInput(e.target.value)
}
id: `node-${schema.nodes.length + 1}`,
content: `Node ${schema.nodes.length + 1}`,
coordinates: [
desiredcoordinates[0],
desiredcoordinates[1],
],
parent: null,
level: 2,
form: null,
className:'button blue',
render: ({id,form}) => (
<div id={id} style={{ fontSize: '0.5rem', textAlign: 'left', padding: '4px', width: '70px', height: '40px' }} onClick={() => toggleSelect(id)}>
<a>
<form style={{ display: form? 'none' : 'block' }}>
<label>Form: </label><input style={{ width: '25px', height: '12px' }} type='text' value={input} onChange={handleChange}></input>
<button type="submit" className='buttonInputSubmit'>+</button>
</form>
<div style={{ display: form? 'block' : 'none' }}> Form: {form}</div>
<div>
</div>
</a>
</div>
)
,
};

How to import just one function from different file into other?

I have a layout file where I made footer and navigation and I insert these two functions in Layout const (code below). In the new file, I just need the Navigation function so how I can insert it without a footer? Because when I write in my new file import Navigation from "../components/layout" and the in code insert I've got error...
const Layout = ({ children }) => {return (
<div>
<Navigation></Navigation>
<Global
styles={{
html: {
backgroundColor: "#fff",
color: "#111",
fontFamily: `'Poppins', sans-serif`,
fontSize: 14,
[Screen.S]: {
fontSize: 16,
},
[Screen.M]: {
fontSize: 18,
},
[Screen.L]: {
fontSize: 20,
},
},
a: {
color: "unset",
},
}}
/>
{children}
<Footer></Footer>
</div>
)
}
function Navigation() { const [navbarOpen, setNavbarOpen] = useState(false) return (
<header
css={{
width: "100%",
maxWidth: "100%",
padding: "0 24px",
position: "fixed",
background: "#fff",
boxShadow: "0 0 0.35rem rgba(0,0,0,.25)",
zIndex: "100",
top: 0,
}}
>
<div
css={{
gridAutoFlow: "column",
minHeight: "4.5rem",
display: "grid",
maxWidth: 1200,
margin: "0 auto",
gridTemplateColumns: "auto 1fr",
alignItems: "center",
paddingLeft: 35,
}}>
<Link to="/ ">
<img style={{ height: "2.5rem" }} src={logo}/>
</Link>
<Toggle
navbarOpen={navbarOpen}
onClick={() => setNavbarOpen(!navbarOpen)}
>
{navbarOpen ? <Hamburger open /> : <Hamburger />}
</Toggle>
{navbarOpen ? (
<NavBoxIcons>
<NavbarSocialLinks />
</NavBoxIcons>
) : (
<NavBox open>
<div>
<HeaderLink>About</HeaderLink>
<HeaderLink>Blog</HeaderLink>
</div>
<div>
<NavbarLinks />
</div>
</NavBox>
)
}
</div>
</header >
)
}
function Footer() { return (
<footer
css={{
padding: "6rem 2rem",
fontSize: "1rem",
minHeight: 160,
fontFamily: "sans-serif",
...Css.container,
}}
>
<div
css={{
display: "flex",
flexDirection: "column",
marginBottom: "3.6rem",
}}
>
<div
css={{
fontSize: "1.2rem",
display: "grid",
gridGap: "0.8rem",
}}>
<a>
<span>Privacy police</span>
</a>
</div>
</div>
<div
css={{
display: "grid",
gridTemplateColumns: "1fr auto",
alignItems: "center",
fontWeight: "lighter",
}}>
<div css={{ display: "flex", flexDirection: "column" }}>
<span>My Page</span>
</div>
</div>
</footer>
)
}
try exporting both Navigation and Footer like this
//at bottom of file
export {Navigation, Footer}
import individual component like this
import {Navigation} from 'components/layout'
or
import {Navigation,Footer} from 'components/layout'
lookup exporting in js

Resources