Send LI value in another input value in React - reactjs

I'm in a React Project, where after an axios.get, I get many LI inside an empty UL before the axios.get.
When the LI are displayed after the axios.get, I want on click on one LI, to send the LI value to an input value.
I know how to do this with Jquery, (examples here: http://jsfiddle.net/Ender/QdWxH/ & http://jsfiddle.net/kbFUu/1/), but I don't know how to do it in React... Can someone help me ?
In my src/App.js I got the function
getValueFromLi = (evt) => {
$('.App-Result-Li').on('click',function() {
var content= $(this).text();
$('.App-Form-Trips-cityDeparture').val(content);
});
}
and in the src/components/Results/index.js (don't worry, I did well with the props, etc.), I got the callback
<li
onClick={getValueFromLi}
data-value={city.local_name}
className="App-Result-Li"
>
Do you know what is wrong in what I did ?
My project is on Github : https://github.com/Versifiction/api-tictactrip
Files involved :
src/App.js (https://github.com/Versifiction/api-tictactrip/blob/master/src/App.js)
& src/components/Results/index.js (https://github.com/Versifiction/api-tictactrip/blob/master/src/components/Results/index.js)
Thank you so much !

maybe you could try like this:
<li
onClick={() => this.provideLocalName(city.local_name)}
data-value={city.local_name}
className="App-Result-Li"
>
also, you could parse the event object in your getValueFromLi function and do something with it then, e.g.
getValueFromLi = e => {
console.log('li element: ', e.target)
// do something with li, now you have reference to the dom node
}
<li
onClick={this.getValueFromLi}
data-value={city.local_name}
className="App-Result-Li"
>

Related

Converting webpage to ReactJS ~ failed to compile "Unexpected use of 'event' no-restricted-globals"

I have some JS code that I need to make compatible with React Web.
I would appreciate some help as I am a little confused with what I need to do.
I get a failed to compile error when I make the following changes.
Currently the onclick function looks like this
<a href="javascript:void(0)" onClick="openMenu(event, 'Starter');">
<div className="w3-col s4 tablink w3-padding-large w3-hover-red">Starter</div></a>
Then I modify the onClick function to this, to attempt to get it to work
``` <a href="javascript:void(0)" onClick={(openMenu) => event, 'Pasta'}>
<div class="w3-col s4 tablink w3-padding-large w3-hover-red">Salads</div> </a>
And the JS function looks like this:
function openMenu(evt, menuName) {
var i, x, tablinks;
x = document.getElementsByClassName("menu");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < x.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" w3-red", "");
}
document.getElementById(menuName).style.display = "block";
evt.currentTarget.firstElementChild.className += " w3-red";
}
document.getElementById("myLink").click();
If I make no changes the function dose not work and my goal is to get this function to work with react web.
Your help would be appreciated.
Just to be clear, you mean the code in the first box doesn't work, and when you try changing it to the second example, you get an error about no-restricted-globals?
This is because you are using a "reserved" keyword (event). So when you change it from the HTML in the first one to a javascript evaluation, the compiler refuses to compile. This is to prevent misalignments of global keywords.
Your almost there with the second example:
<a href="javascript:void(0)" onClick={(openMenu) => event, 'Pasta'}>
currently you have the function name in parens (openMenu) which isn't what you mean. The parens take the arguments you want to call the function with.
Something like
<a href="javascript:void(0)" onClick={(event) => openMenu(event, 'Pasta')}>
should work. The key thing I did was change how you are calling the function. If you have more questions about arrow functions, the React docs can be helpful. It just takes a while to get used to the new ES6 syntax.
Another way to solve this could use function currying:
<a href="javascript:void(0)" onClick={openMenu('Pasta')}>
then the function could be rewritten as such:
const openMenu = (menuName) => event => { ...
event.currentTarget.firstElementChild.className += " w3-red";
either of the ways presented will solve the problem for you (and many other ways as well).

How to conditionally set HTML attributes in JSX using reason-react?

I want to render an HTML checkbox whose checked state is controlled by data.
Give a stateless component that receives an item type { label: string, checked: bool},
Like so:
let component = ReasonReact.statelessComponent("TodoItem");
let make = (~item, _children) => {
render: _self => {
<li> <input type_="checkbox" {/*looking for something like this*/ item.checked ? "checked" : "" /* doesn't compile */}/> {ReasonReact.string(item.label)} </li>
}
}
How do I add the presence of the attribute checked to the input tag based on the item.checked == true condition?
As #wegry said in a comment, it seems to fit your use case better to just pass the value directly since item.checked already is a boolean, and checked takes a boolean.
But to answer more generally, since JSX attributes are just optional function arguments under the hood, you can use a neat syntactic trick to be able to explicitly pass an option to it: Just precede the value with ?. With your example:
let component = ReasonReact.statelessComponent("TodoItem");
let make = (~item, _children) => {
render: _self => {
<li> <input type_="checkbox" checked=?(item.checked ? Some(true) : None) /> {ReasonReact.string(item.label)} </li>
}
}
Or, to give an example where you already have an option:
let link = (~url=?, label) =>
<a href=?url> {ReasonReact.string(label)} </a>
This is documented in the section titled Explicitly Passed Optional on the Function page in the Reason docs.

React, dynamically add text to ref span

I'm trying to render a message to a span tag specific to an item in a list. I've read a lot about React 'refs', but can't figure out how to populate the span with the message after it's been referenced.
So there's a list of items and each item row has their own button which triggers an API with the id associated with that item. Depending on the API response, i want to update the span tag with the response message, but only for that item
When the list is created the items are looped thru and each item includes this
<span ref={'msg' + data.id}></span><Button onClick={() => this.handleResend(data.id)}>Resend Email</Button>
After the API call, I want to reference the specific span and render the correct message inside of it. But I can't figure out how to render to the span at this point of the code. I know this doesn't work, but it's essentially what I am trying to do. Any ideas?
if (response.status === 200) {
this.refs['msg' + id] = "Email sent";
I recommand using state. because string refs legacy (https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs)
const msgs = [
{ id:1, send:false },
{ id:2, send:false },
{ id:3, send:false },
];
this.state = {
msgs
};
return this.state.msgs.map((msg, index) => {
const status = msg.send ? "Email Sent" : "";
<span>{ status }</span><Button onClick={() => this.handleResend(index)}>Resend Email</Button>
});
async handleResend (index) {
const response = await callAPI(...);
if(reponse.status !== 200) return;
const newMsgs = _.cloneDeep(this.state.msgs);
newMsgs[index].send = true;
this.setState({
msgs: newMsgs
})
}
The workaround is set innerText
this.refs['msg' + id].innerText = "Email sent";
But rather than using ref try to use state to update elements inside render.
i was facing with this issue right now and i figured it out this way:
// currentQuestion is a dynamic Object that comes from somewhere and type is a value
const _target = `${currentQuestion.type}_01`
const _val = this[`${_target}`].current.clientHeight // here is the magic
please note that we don't use . after this to call the ref and not using refs to achieve what we want.
i just guessed that this should be an Object that would hold inner variables of the current object. then since ref is inside of that object then we should be able to call it using dynamic values like above...
i can say that it worked automagically!

Reactjs, how to instanciate object from array, and update render

I'm struggling with reactjs for no reason. I'm a little confused about the magic behind and I'm not able to perform a simple operation of adding object / removing object from an array and display it.
I my parent, I have a method which on click append a new element:
appendNewPma(){
var newPma = this.state.pma.slice();
newPma.push(PmaType1);
this.setState({pma:newPma})
}
then my render method is like that:
render() {
return (
<div>
<a className="waves-effect waves-light btn" onClick={this.appendNewPma}>new</a>
{this.state.pma.map((Item, index) => (
<Item
key = {index}
ref = {"pma" + index.toString()}
onDelete = {() => this.onDelete(index)}
title = {index}/>
))}
</div>
);
}
Append work fine, but my array doesn't contain an object to display but rather a magical function that I don't understand.
But when I try to delete an object:
onDelete(idx){
console.log(idx);
var pma = this.state.pma.slice();
pma.splice(idx, 1);
this.setState({pma:pma})
}
When I delete from the array, no matter what index I will remove, it will only remove the last object. I know my code is not ok, but I have no idea how you can render element for an array of object (here my array is list of function constructor).
It will work better if I could get a straight ref to my object. Of course, I tryed to removed from the ReactDom, but was complening I was not updating from the parent...
I just want a simple array push/pop pattern with update.
Thanks for your help
Try below code. hope so it solve your issue.
addToArray = (event) => {
this.state.pma.push({"name ": "xyz"});
this.setState(
this.state
)
}
removeFromArray =(index) => {
var updatedArr = this.state.pma.splice(index, 1);
this.setState({arr : updatedArr})
}

Render an Element with React

Honestly I don't think that this is the best Title, but I've no idea how explain it.
So sorry for it.
I'm trying to write a Component that parse all links(thar are not into a anchor tag) and emoji and render it like links or image.
For emoji I'm using this amazing component: https://github.com/banyan/react-emoji
It works well, but the problem is with the simple links...I don't have found a way for render it like links, instead of text of the link tag.
This is my code:
# #cjsx React.DOM
#Linkify = React.createClass
displayName: 'Linkify'
mixins: [ReactEmoji]
componentDidMount: ->
componentWillUnmount: ->
render: ->
<div>
{#parseLinks(#props.text)}
</div>
parseLinks: (text) ->
pattern = /(ht|f)tps?:\/\/[^\"<]*?(?=\s|$|<\/[^a]>)/gi
results = text.match(pattern)
new_text = text
if results and results.length > 0
for result in results
link_html = React.createElement('a', {href: result}, result)
new_text = new_text.replace(result, link_html)
return #emojify(new_text)
and if I wrote:
Hello search here google.com :)
I get:
Hello search here [object Object] :) (instead of :) I've the correct emoji image)
The problem is: why it don't show correctly the Object Link ? where I done wrong ?
Thanks for any help.
link_html = React.createElement('a', {href: result}, result)
new_text = new_text.replace(result, link_html)
You can't use String#replace to put an object (returned by React.createElement) into a string. It's like saying
var text = "one two three";
var el = {testing: true};
alert(text.replace("two", el));
Instead, you should return a ReactElement (created with JSX or React.createElement) that contains the associated text, but with the link in the correct place in the children.
Consider the output of
<span>Test google.com link</span>
which is
React.createElement("span", null,
"Test ",
React.createElement("a", {href: "google.com"},
"google.com"
),
" link"
)

Resources