If my api takes the query as http://localhost:8000/api/v1/rental/?place__startswith=kathmandu then how can i do generic search in reactjs. What i tried is i passed the default parameter as search(query=kathmandu) so that the result of place named kathmandu will be listed by default and when user types place name that they want to search then it should display those places instead of kathmndu. But i am getting an error saying Uncaught ReferenceError: kathmandu is not defined. How can i resolve this problem?
componentWillMount(){
this.search();
}
search(query=kathmandu){
let url = 'http://localhost:8000/api/v1/rental/?place__startswith=query';
Request.get(url).then((response) => {
console.log('response',response.body.objects);
this.setState({
place:response.body.objects
});
});
}
searchUpdated(term){
console.log('term is',term);
this.search(term);
}
render() {
var margin = { marginTop : '13em' };
let location = _.map(this.state.place, (place) => {
return(
<div className="searchResult">
<li>{place.place}</li>
<li>{place.city}</li>
</div>
)
});
return(
<div className = "container">
<div className="content text-align-center">
<div className="row text-xs-center">
<div className="middle-text" style={margin}>
<h1 className="welcome"><span>Welcome </span></h1>
<button ref="test" className="btn how-it-works" onClick={this.handleClick}>Search Space</button>
</div>
</div>
</div>
<div id="mySearch" className="overlay" onKeyDown={this.handleKeyDown}>
<button className="btn closebtn" onClick={this.handleClick}>x</button>
<div className="overlay-content">
<SearchInput ref="searchInput" className="search-input" onChange={this.searchUpdated} />
<ul>{location}</ul>
</div>
</div>
</div>
);
}
}
I think what you're looking for is encodeURIComponent.
search( query='kathmandu' ){
And:
let url = 'http://localhost:8000/api/v1/rental/?place__startswith=' + encodeURIComponent(query);
NB as your query string actually does only contains letter, you don't need encodeURIComponent for that example, but you might need it in other cases.
Related
I have a lit element based javascript project, when I want to throw an html tag with .replace in a text, I encounter either the value with the tag or a structure in the form of object, object, I made a structure as follows, what am I doing wrong?
basicly my values
main-text = abc dcf [0] xyz
bold-text = 123
and my render here
render() { return html`
<section >
<div class="blablaclass" #click = ${() => this.clickfnc()} >
<div class="blablaclass1">
${html`<span> ${this.t('main-text').replace('[0]', this.renderCardText )} </span>`}
</div>
<div>
<img class="blablaclass2" src="./resources/right-arrow.svg"/>
</div>
</div>
</section>`;
}
get renderCardText(){
return html`<strong>this.t('bold-text')</strong>`;
}
and outputs
output: acv dcf [] xyz
without call html in function just return output: acv dcf <strong>123</strong> xyz
The html tag function returns a TemplateResult object so you can't use it as a replacement in String.prototype.replace().
There are a couple different options for what you want to do:
Split the string instead of replacing and combine them piece by piece.
render() {
const [before, after] = this.t('main-text').split('[0]');
return html`
<section >
<div class="blablaclass" #click = ${() => this.clickfnc()} >
<div class="blablaclass1">
${html`<span>${before}${html`<strong>${this.t('bold-text')}</strong>`}${after}</span>`}
</div>
<div>
<img class="blablaclass2" src="./resources/right-arrow.svg"/>
</div>
</div>
</section>`;
}
This can get tricky if you have more than 1 things to replace.
Replace as string and use the unsafeHTML directive.
render() {
return html`
<section >
<div class="blablaclass" #click = ${() => this.clickfnc()} >
<div class="blablaclass1">
${html`<span>${unsafeHTML(this.t('main-text').replace('[0]', `<strong>${this.t('bold-text')}</strong>`))}</span>`}
</div>
<div>
<img class="blablaclass2" src="./resources/right-arrow.svg"/>
</div>
</div>
</section>`;
}
Make sure you trust the string you put in there.
Not sure why I'm getting this error. I need to loop through the variations and find the id's containing the varid variables. To me this looks right but it's obviously not. I'm sure everyone here is much smarter than me though haha, I'm still very much a newbie at all this.
This function is supposed to allow me to filter down the state so that I have only the needed data and can display that within the page rather than the state containing all of my drupal products. Perhaps there's a more efficient way to do this also, I'm not sure.
Here's the code:
class ProductPage extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
dropdownOpen: false
};
}
toggle() {
this.setState(prevState => ({
dropdownOpen: !prevState.dropdownOpen
}));
}
render() {
let style = {
height: this.props.height - 56,
};
let product = this.props.products.items.find(o => o.path[0].alias === this.props.router.match.url);
console.log(product);
console.log(this.props.variations);
let variationList = [];
if (product && this.props.variations) {
for (let i = 0; i < product.variations.length; i++) {
let varid = product.variations[i].variation_id;
let variation = this.props.variations.find(o => o.path[0].alias === varid);
variationList.push(variation);
}
}
let body = product && product.body.length ? product.body[0].value : null;
return (
<div className="App" id="default">
<div className='MenuBar'>
<MenuBar/>
</div>
<div>
<div style={style} className="ProductPage row no-gutters">
<div className="col-xs-3 col-md-3">
<LeftMenuBar/>
</div>
<div className="outer col-xs-4 col-md-4">
<div>
<div id="ProductPlacement">
<img src={WomensWear} alt=""/>
<div id="alternate-pics">
<div id="alt-pic">
</div>
<div id="alt-pic">
</div>
<div id="alt-pic">
</div>
</div>
</div>
</div>
</div>
<div className="col-xs-5 col-md-5">
<div id="ImagePlacement">
<div className="ProductTitle">
<h1>First Product</h1>
</div>
<hr/>
<div className="ProductDescription">
<div dangerouslySetInnerHTML={{__html: body}} />
</div>
<div id="options">
<div id="color">
</div>
<div id="color2">
</div>
<div id="color3">
</div>
</div>
<div id="options">
<div>
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle}>
<DropdownToggle caret id="size-dropdown">
Size
</DropdownToggle>
<DropdownMenu>
<DropdownItem>1</DropdownItem>
<DropdownItem>3</DropdownItem>
<DropdownItem>5</DropdownItem>
</DropdownMenu>
</Dropdown>
<div className="AddToCart">
<button className="AddToCart">Add To Cart</button>
<button className="Price">$34.99</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default ProductPage;
I also ran into this issue and through trial and error discovered it was because of copy+paste. Check your reducer(s) to make sure you aren't setting a default of an object {} or other type, instead of an array [].
In my case I had (this is ES6 syntax by the way):
const someReducer = (state = {}, action) => {
switch (action.type) {
case 'reducer type':
// get the data etc.
return [];
default:
return state;
}
};
When I should have had:
const someReducer = (state = [], action) => {
switch (action.type) {
case 'reducer type':
// get the data etc.
return [];
default:
return state;
}
};
Notice the first line where I'm setting the default. This is used while the api calls are pending, so if it just happens to reach the code where .find() is being used then you'll get the error.
This is extremely easy to miss because data is retrieved so fast that you can't easily see when the data is the wrong type. Just make sure your default, however you're setting it, is the correct type! Hope that helps someone!
hope you're all doing great, I was just curious to know what could be an ideal place for listening events pushed from server, I'm playing with socket-io and trying to make a chat application in which the server pushes messages to the client, here is the code
getInitialState:function(){
return {localstatemessages: ['hi'],remoteuserstatemessages:['hello']}},
render: function () {
this.ListenEvents();
var localusermsgs=this.state.localstatemessages.map(function(Message){
return(
<SendMessage Message={Message}/>
)
});
var recievedmsgs=this.state.remoteuserstatemessages.map(function(msg){
return(
<RecievedMessage Message={msg} />
)
})
return (
<div className="col-lg-8 col-md-8 col-xs-8 pull-right">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div className="row">
<div className="page-header">
<div className="media">
<div className="media-left">
<img src={require("../_assets/_images/download.jpeg")} className="img-circle" alt="user image" />
</div>
<div className="media-body">
<h2 className="media-heading">peer user</h2>
</div>
<div className="media-right"></div>
</div>
</div>
</div>
</div>
<div className="chat_box">
<RecievedMessage Message={this.state.remoteusermsg}/>
<SendMessage Message={this.state.usermsg}/>
</div>
<div className="msg_area">
<div className="row">
<div className="col-lg-12">
<div className="input-group">
<textarea type="text" cols="5" rows="2" onKeyDown={this.sendMessage} className="form-control" placeholder="Type here..."></textarea>
<span className="input-group-btn">
<button className="btn btn-warning" type="button" onClick={this.sendMessage}>send</button>
</span>
</div>
</div>
</div>
</div>
</div>
)
},
sendMessage: function (event) {
if (event.keyCode == 13) {
let target = event.target;
var msg = target.value;
// alert('message is: ' + msg);
//event raising through ajax goes here
socket.emit('chat mssg',msg);
// alert('pushing msg ');
var newlocalmsg= this.state.localstatemessages;
newlocalmsg.push(msg);
this.setState({localstatemessages:newlocalmsg});
target.value='';
}
},
handleRemoteMesssageUpdate:function(message){
var remotemessages=this.state.remoteuserstatemessages;
remotemessages.push(message);
this.setState({remoteuserstatemessages:remotemessages})
},
ListenEvents:function(){
socket.on('chat mssg',function (msg){
// alert('pushing anothermsg');
this.handleRemoteMesssageUpdate(msg);
}.bind(this));
}
});
module.exports = ChatBox;here
the state remoteuserstatemessages updates three times for a single pushed events , i don't understand what is going on here, does the render function calls the ListenEvents repetitively ? how can it be done?
You put this.ListenEvents() in render(), of course it will be called for many times.
Since you are using socket, you just need to intialize the connection once right? So better you call it in componentWillMount()
componentWillMount(){
this.ListenEvents()
}
render(){
// render code
}
More about React Component Lifecycle : https://facebook.github.io/react/docs/react-component.html
When I run this code, I get a bootstrap panel group for each recipe item inside of local storage. When I try to delete a recipe, sometimes the right recipe is removed and sometimes not. The console shows that the right recipe is removed from local storage but for some reason when the app component resets its state, the wrong recipe is removed. I've noticed that if I try to delete the recipes from the bottom up, it works. But if I click on the first recipe, the bottom recipe is removed.
I know this is an easy fix but I need a fresh perspective. Thanks everyone!
Also, sorry lack of indentation in the code - stack overflow wasn't being too friendly with the spacing
class App extends Component {
constructor() {
super();
this.deleteRecipe = this.deleteRecipe.bind(this)
this.state = {
recipeData: JSON.parse(localStorage.getItem('recipeData'))
}
}
deleteRecipe() {
this.setState({recipeData: JSON.parse(localStorage.getItem('recipeData'))})
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React Recipe Box!</h2>
</div>
<div className="container">
{this.state.recipeData.map(recipe => {
return (
<Recipe name={recipe.name} ingredients={recipe.ingredients} deleteRecipe={this.deleteRecipe}/>
)
})}
</div>
</div>
);
}
}
class Recipe extends Component {
constructor() {
super();
this.onDeleteRecipe = this.onDeleteRecipe.bind(this)
}
componentWillMount(){ //set state when component is about to mount
this.state = {
name: this.props.name,
ingredients: this.props.ingredients,
}
}
onDeleteRecipe() {
var recipeList = JSON.parse(localStorage.getItem('recipeData'));
for(var i = 0; i < recipeList.length; i++) {
if(recipeList[i].name === this.state.name) {
recipeList.splice(i, 1);
console.log("Deleted " + this.state.name, recipeList);
localStorage.removeItem('recipeData');
localStorage.setItem('recipeData', JSON.stringify(recipeList));
this.props.deleteRecipe();
}
}
}
render() {
return (
<div>
<div className="panel-group">
<div className="panel panel-primary">
<div className="panel-heading">
<h2 className="panel-title">
<a data-toggle="collapse" data-target={'#' + (this.state.name).replace(/\s/g, '')} href={'#' + (this.state.name).replace(/\s/g, '')}>
{this.state.name}
</a>
</h2>>
</div>
<div id={(this.state.name).replace(/\s/g,'')} className="panel-collapse collapse">
<div className="panel-body">
{this.state.ingredients.map(ingredient => {
return <li className="list-group-item">{ingredient}</li>
})}
<div className="btn-group">
<button className="btn btn-sm btn-info" data-toggle="modal"
data-target={'#' + (this.state.name).replace(/\s/g, '') + 'EditModal'}>Edit</button>
<button className="btn btn-sm btn-danger" data-toggle="modal"
data-target={'#' + (this.state.name).replace(/\s/g, '') + 'RemoveModal'}
>Delete</button>
</div>
</div>
</div>
</div>
</div>
<div className="modal modal-lg" id={(this.state.name).replace(/\s/g, '') + 'EditModal'} >
<div className="modal-content">
<div className="modal-header">
<h2>Edit {this.state.name}</h2>
</div>
<div className="modal-body">
<ul className="list-group list-unstyle">
{this.state.ingredients.map( ingredient => {
return <li className="list-group-item">{ingredient}</li>
})}
</ul>
</div>
<div className="modal-footer">
<div className="btn-group">
<button className="btn btn-sm btn-info" data-dismiss="modal">Save</button>
<button className="btn btn-sm btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div className="modal modal-lg" id={this.state.name.replace(/\s/g, '') + 'RemoveModal'}>
<div className="modal-content">
<div className="modal-body">
<h3>This will remove the selected recipe. Are you sure?</h3>
</div>
<div className="modal-footer">
<div className="btn-group">
<button className="btn btn-sm btn-danger" data-dismiss="modal" onClick={this.onDeleteRecipe}>Delete</button>
<button className="btn btn-sm btn-info" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
I'm still a novice, but... I built a react recipe box for FreeCodeCamp a few months ago, so I just pulled it up to compare my delete function to yours.
I notice that you treat localStorage differently than I did in mine. (Not that my way is best or even right!) I wonder if somehow the problem is rooted in that design. Your delete function goes into localStorage and makes changes, then you run a setState to sort of "re-get" the recipeData, if I'm reading right?
By contrast, my app declares a variable from localStorage and I set this.state.recipeArray to equal that variable. Then all of my edit/add/delete functions change this.state.recipeArray, not localStorage. Sorta like this:
handleDelete: function(e) {
e.preventDefault();
var replacementRecipeArray = this.state.recipeArray.filter((recipe) => recipe.title !== e.target.name);
//dot-filter with ES6 fat-arrow returns all items where title doesn't match the one we clicked; IOW, it removes the one we want to delete
this.setState({
recipeArray: replacementRecipeArray
});
}
In order to get any changes to this.state.recipeArray back to localStorage, I do a localStorage.setItem every time I render the page.
render() {
//first save current array to localstorage - wasn't reliable anywhere else
localStorage.setItem("_shoesandsocks_recipes", JSON.stringify(this.state.recipeArray));
//render page
return (
<div className="App">
<div className="recipeContainer">
// etc etc
For all I know this is a crazy design, but it works.
I have a searching system where user search by typing the place. If the place does not match, it should show not found and if place matches, it should show the place detail. What I did is
code
render() {
var margin = { marginTop : '13em' };
if (this.state.place){
let location = _.map(this.state.place, (place,id) => {
return(
<Room key={id}
slug={place.slug}
place={place.place}
city={place.city}
gallery={place.gallery}
property={place.property}/>
)
console.log('location',location);
});
let gallery = _.map(this.state.place, (place,id) => {
console.log('place',place.gallery);
_.map(place.gallery, (image,id) => {
return(
<img src={image.image} class="img-fluid" />
)
});
});
let noLocation = () => {
return(
<div className="noroom">There is no room</div>
);
console.log('nolocation');
};
return(
<div className = "container">
<div className="content text-align-center">
<div className="row text-xs-center">
<div className="middle-text" style={margin}>
<h1 className="welcome"><span>Common Rental Space</span></h1>
<p className="appSubtitle">facilitates your search for rental space all over Nepal</p>
<button ref="test" className="btn how-it-works" onClick={this.handleClick}>Search Space</button>
</div>
</div>
</div>
<div id="mySearch" className="overlay" onKeyDown={this.handleKeyDown}>
<button className="btn closebtn" onClick={this.handleClick}>x</button>
<div className="overlay-content">
<SearchInput ref="searchInput" className="search-input" onChange={this.searchUpdated} />
<div className="container searchList">
{ this.state.place > 1 ? {location} : {noLocation} }
</div>
</div>
</div>
</div>
);
}
}
}
What might be the error? The syntax is { condition ? true : false }
When I do {this.state.place >1 ? { location } : {noLocation} } I get an error
app.js:1030 Uncaught Invariant Violation: findComponentRoot(..., .0.1.1.1.0.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables, nesting tags like <form>, <p>, or <a> or using non-SVG elements in an <svg> parent. Try inspecting the child nodes of the element with React ID ``.
When I do this.state.place >1?{location}:{noLocation}i get this.state.place >1 ? result, and if place does not match the page shows this.state.place >1 ? :.
noLocation appears to be a method, but you aren't actually calling the method anywhere - so you are basically telling reaction to render the function itself, not the result of the method.
If it must be a method, try, noting the extra ():
{ this.state.place.length >=1 ? location : noLocation() }