In react, how to pass a dynamic link in sms href? - reactjs

React-share is a nifty tool but.... doesn't have sharable sms support that I can find. Need some pointers. //will send virtual coffee as a thanks!B)
The challenge: share a dynamically created product url as a text message, with the dynamic description and url.
I have tried several link additions, but not able to accomplish the result I am looking for. Here is most recent try:
<FontAwesome name="share" />
Another one I tried (which is what I use for non-dynamic links) at least drops text into the body is:
<FontAwesome name="share" />

After working this through, here is what we ended up going with, no phone number at all, just the description and url in the body of the message.
First:
const objectEncode = object => {
const str = [];
Object.keys(object).forEach(key => {
str.push(`${encodeURIComponent(key)}=${encodeURIComponent(object[key])}`);
});
return str.join('&');
};
export default objectEncode;
Then:
import objectEncode from '../../../utils/objectEncode';
Then within the component:
render(){
const smsBody = objectEncode({ body: `${description} ${url}` });
return (
<a href={`sms://?&${smsBody}`} className="social-link">
<FontAwesome name="commenting" />
</a>
);
}

Related

React-Intl pass translation as string variable and not object

I'm in the process of adding react-intl to a payment app I'm building but hitting a snag. I apologize if this has been addressed somewhere. I scoured the issues and documentation and couldn't find a direct answer on this (probably just overlooking it).
Use Case: Once a payment is processed I'd like to give the user the option to tweet a translated message indicating they've donated.
Problem: Twitter uses an iframe to "share tweets", and requires a text field as a string variable. When I pass my translation I get [object Object] in the tweet instead of the translated text. This makes sense based on my understanding of the translation engine. But I cant seem to find a way to pass a string rather than a translation object.
what I get when I use {translate('example_tweet')}
const translationText = object
what I need
const translationText = 'this is the translated text'
Question
How do I get the translated text as a string variable rather than an object to be rendered on a page?
Code
button
import { Share } from 'react-twitter-widgets'
import translate from '../i18n/translate'
export default function TwitterButton () {
return (
<Share
url='https://www.sampleSite.org' options={{
text: {translate('example_tweet')},
size: 'large'
}}
/>
)
}
translate
import React from 'react'
import { FormattedMessage } from 'react-intl'
const translate = (id, value = {}) => <FormattedMessage id={id} values={{ ...value }} />
export default translate
I was able to solve it without messing with react-intl. I built a function that scrapes the text I need from the page itself. So it really doesnt matter what the language is. I was hoping to figure out how to snag the translations as variables, but this gets the job done.
function makeTweetableUrl (text, pageUrl) {
const tweetableText = 'https://twitter.com/intent/tweet?url=' + pageUrl + '&text=' + encodeURIComponent(text)
return tweetableText
}
function onClickToTweet (e) {
e.preventDefault()
window.open(
makeTweetableUrl(document.querySelector('#tweetText').innerText, pageUrl),
'twitterwindow',
'height=450, width=550, toolbar=0, location=0, menubar=0, directories=0, scrollbars=0'
)
}
function TwitterButton ({ text, onClick }) {
return (
<StyledButton onClick={onClick}>{text}</StyledButton>
)
}

How to Jump to Redux State with Browser Back Button

I’m a react beginner and I have a project using React Router (4.2.2), Redux and I’ve recently added react-router-redux hoping that it would solve my problem. I have components whose redux stored states need to change based on interactions with the browser back and forward buttons.
For example, I have a screen containing details for an element the user clicked. If I use the browser back button and navigate to another point in history in which that details view was open, it will only show the most recent element info (due to that the only information in the store) or sometimes no information at all will be passed.
I thought react-router-redux would help me keep these two in sync but maybe I’m missing a step that enables that to happen. I’ve installed Redux Debug Tools and I can see in there the state that I want to jump to, but how do I enable it when the user uses the back button? The url for the details page is the same each time it’s viewed, perhaps I need to add a hash tag with specific information but even then, how would I do a look up for the correct information in the store?
I open the details view like this:
<Link to='/activityDetails'>
<ActivityButton
id={this.props.someData.someId}
/>
</Link>
And inside ActivityButton:
openActivityDetails = () => {
this.props.showActivityDetailsScreen(this.props.id);
};
function matchDispatchToProps(dispatch) {
return bindActionCreators({
showActivityDetailsScreen: activityDetailsActions.showActivityDetails
}, dispatch)
}
render(){
return (
<div className={'activity-button'} onClick={this.openActivityDetails}>
<img
onClick={this.handleClick}
src={imgPath}
/>
</div>
);
}
So I figured it out on my own. Essentially what you need to do is set the state information inside the when you create it, like so:
<Link to={{
pathname: '/activityDetails',
state: { "activityData": activityData }
}}>
<ActivityButton
id={this.props.someData.someId}
/>
</Link>
then in the class you need the information ActivityDetails in my case you can query it like this:
var actData = this.props.location.state.activityData;
or if you're using withRouter and history it's also in the following location:
const { history: { push } } = this.props;
history.state.state.activityData
I ended up removing react-router-redux because it wasn't necessary. It made an entry in the state with the current route, but in my case that wasn't useful. Hope this helps someone in the future.

React InstantSearch : onSearchStateChange get the number of returned hits

I am using the react instant search by algolia and i have a requirement to show an overlay every time there is result.
so i want to handle it via onSearchStateChange function provided by algolia. but i am still puzzled where to get the total hits. i already have an idea which is very quick like using the results displayed in the by extracting the numbers via jquery. but i don't want to do it. is there other way you can suggest?
onSearchStateChange(nextState) {
//must get the number of total hits.
nextState = cleanDeep(nextState);
let filters = transformer(nextState);
this.setState({
searchState: nextState,
filters: filters,
searchChanged: true
})
this.sendToAti(filters);
this.addOverlay(); // <--- function that will show the overlay.
location.hash = qs.stringify(nextState);
}
The onSearchStateChange function doesn't contain the searchResults object where you can find the number of hits.
However, we provide a <Stats> widget and a connectStats connector that contain this information. Maybe you could use that?
Basically, as pointed by #Marie and documented in the links she pointed, you need to follow a 3 step process:
1.- Create a custom component:
export default function MyStatefullComponent({ searchResults }){
const hasResults = searchResults && searchResults.nbHits !== 0;
const nbHits = searchResults && searchResults.nbHits;
//Handle State Mutations Here
return return (hasResults) ? <div className="shadow-xl mb-4 ml-4 p-8 ">
Has Results
</div>
:
<div>Has No Results</div>
}
2.- connect to the component using the connector
Once you have your custom component, use the connectStateResults
import { connectStateResults } from 'react-instantsearch-dom';
export default function OtherComponent(){
const StatefullComponent = connectStateComponent(MyStatefullComponent);
return <StatefullComponent />
}
3.- import/add the component to your other component.

onClick not being called ReactJS

Before downvoting, I've been through plenty of other solutions on SO around this same issue and can't find an answer that resolves this issue.
I'm having trouble trying to get the onClick attribute to fire off my function, here's a piece from the problematic component:
Constructor:
constructor() {
super();
this.state = {
submissionFormCount: 0
}
this.addToSubmissionFormCount = this.addToSubmissionFormCount.bind(this);
}
render:
<div className="row">
<div className="col s12 m12 l12">
<h5 onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</h5>
</div>
</div>
clickHandler:
addToSubmissionFormCount() {
alert('Here');
this.setState({
submissionFormCount: this.state.submissionFormCount++
});
}
I'm rendering the app from an Express server using 'react-dom/server'
Here's how I am rendering the component:
exports.beatSubmission = (req, res) => {
const appString = renderToString(<App type="beatSubmission"/>);
res.send(beatSubmissionTemplate({
body: appString
}))
}
I think you're only rendering your react components on the server side. The reason I think this is because of the following code you've copied:
exports.beatSubmission = (req, res) => {
const appString = renderToString(<App type="beatSubmission"/>);
res.send(beatSubmissionTemplate({
body: appString
}))
}
You're rendering the component to a string and shipping the string to the frontend as static HTML. While this will indeed give you properly rendered markup, it will result in a non-interactive app.
To have click handlers work, you also need to compile your JS, and include it for use on the frontend like this:
https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/server.js#L76
renderToString(<Html assets={webpackIsomorphicTools.assets()} store={store}/>));
There are a few ways to do this. You can manually add a script file with your JS pre-packaged for the frontend in your template or you can use Webpack Isomorphic Tools.
I suspect you read a react tutorial that lead you down the isomorphic (server/client side rendered) path. You can run react on the server, the client side or both. Running it on both takes some work, but results in an app that "feels" faster.
I can't see any problem with the code. However, the only thing that comes to my mind is if you're rendering the <h5> in a function of some sort, maybe mapping and array for example. If so, you need to define var self = this in the render function before the return, then use self.addToSubmissionFormCount.
P.S. I don't recommend using onClick handler in <h5> tag
Change your h5 into an anchor tag. So replace:
<h5 onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</h5>
with:
<a onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</a>
You can style your anchor anyway you want afterwards. For example if you want to not have a cursor when hovering then add cursor: none
You should not mutate the state of react.
Change:
this.state.submissionFormCount++
To:
this.state.submissionFormCount+1

React-select auto loading options

This if my first question on SO so hopefully I dont forget anything.
I am currently developing a site with React that allows the customer to type in the first few letters of a vehicle name and it searches the database bringing back results. I am also accessing this site directly from another site via react-router and an iframe.
When I am coming in from the external site, I will be passing a query to react-router. The query will come in something like:
http://localhost:9292/#/?id=362789&start=1446015600000&stop=1446101999999
I would like react-select to automatically getOptions if "id" was included in the query. Otherwise I would like it to continue to wait for user input as it is working now.
My current code looks something like. I know I will need a if/else statement but more concerned with the auto-loading factor for now:
render() {
const asset_id = this.props.id
const getOptions = (input) => {
return fetch(`/subject?q=${input}`, {credentials: 'include'})
.then((response) => {
return response.json();
}).then((data) => {return {options: data}});
}
return (
<div className="picker">
<Select.Async
loadOptions={getOptions}
minimumInput={2}
value={this.state.selectValue}
onChange={this.updateValue.bind(this)}
ref="dropdown"
name="chooser"
/>
</div>
}
Any help you could give would be wonderful. Im still getting familiar with React and I feel I am overlooking something simple possibly.

Resources