Flunetui TextField has a prop for onRenderSuffix where I can render a Spinner component to indicate that a save call is being made. However, comboBox doesn't have something like that from looking at the IComboBoxProps interface. Any idea how I can implement the following like I am doing with textBox?
onRenderSuffix: () => {
return (
<>
{isSubmitting && (
<TooltipHost
id="goal-saving-id"
content="some content"
>
<Spinner aria-describedby="goal-saving-id" />
</TooltipHost>
)}
</>
);
}`
Related
Issue:
Right now, I have a dynamic route that fetches data using getServerSideProps(). Within this page, there are multiple tabs that renders different data depending on state (which tab is selected).
I wish to transition from using multiple tabs on this page, to instead using nested routes. However, I am having difficulty obtaining the data originally fetched in these nested routes. Is there an efficient way of doing so, without having to call getServerSideProps() again?
My intended setup looks like this, where [page] calls getServerSideProps():
[page].jsx
|_tab1.jsx
|_tab2.jsx
|_tab3.jsx
My current [page].jsx, where I would like to use separate, nested pages that have access to these props (instead of rendering each tab based on state):
export default function Page(props) {
const [currentTab, setCurrentTab] = useState("home");
return (
<div>
<div id="tab1" onClick={() => setCurrentTab("home")}>
home
</div>
<div id="tab2" onClick={() => setCurrentTab("posts")}>
posts
</div>
<div id="tab3" onClick={() => setCurrentTab("info")}>
info
</div>
{currentTab === "home" ? (
<HomeTab props={props}/>
) : currentTab === "posts" ? (
<PostsTab props={props}/>
) : (
<InfoTab props={props}/>
)}
</div>
);
}
Attempts
I've attempted using the context API to utilize data globally, which my other pages can use. However, this requires the user to visit the original dynamic route first.
Call getServerSideProps() on each nested route. Although this works, I wish to find a better solution, since I'm fetching data on each nested route while the route they're nested under has all of this data available already.
You can use shallow routing in next/route or next/link
Note that, in the below example, I'm using next/link for the demonstration. Without your tab data, I'd assume you have an array of tabs in data
import { useEffect } from 'react'
import Link from 'next/link'
//the path is `/tab/:tabId`
function Tab({ data }) {
const [tabData, setTabData] = useState(data[0]) //first tab data as default for example
useEffect(() => {
setTabData(data[tabId])
}, [router.query.tabId])
return <>
<Link href="/tab/0" shallow />
<Link href="/tab/1" shallow />
<div>
{tabData}
</div>
</>
}
export async function getServerSideProps(context) {
return {
props: {
data: [], //tabs' data you fetched from the API
},
}
}
export default Tab
I am making a button that is going to say "disable" when its on and "enable" when its off. how do I do that in react?? I have tried to make it but I have no idea where to even start, is there some syntax im missing?
The code below does the job of displaying the button text based on a state.
Inside the useState() hook you can specify the initial state.
On the button's click event the state will be reversed to toggle between true and false
const customButton = () => {
const [enabled, setEnabled] = useState(false);
return (
<button
onClick={() => setEnabled(!enabled)}>
{enabled ? "disable" : "enable"}
</button>
);
}
Am implementing the Algolia search in my NextJS app. I have the datasource and indices already setup. What am trying to setup is something like what Gucci is doing in their search. Gucci is using Algolia for their search functionality.
I tried using the react-instantsearch-dom package of Algolia. And I updated my /pages/_app.js file like this(only relevant code is written here):
/**
* /pages/_app.js
*
*/
//-------- Algolia
import algoliasearch from 'algoliasearch/lite';
import { InstantSearch } from 'react-instantsearch-dom';
const searchClient = algoliasearch( 'xxxxxxxxxx', 'yyyyyyyyyyyyyyy' );
//-------- /Algolia
function MyApp({ Component, pageProps }) {
return (
<>
<InstantSearch searchClient={searchClient} indexName={ 'abc_test_products' }>
<Component {...pageProps} />
</InstantSearch>
</>
)
}
export default MyApp
This way I could use the components of react-instantsearch-dom anywhere.
Am confused at three things here.
Doubt 1:
How can I pass the algolia query and filters to the search results page like here and display the results using the components : https://www.gucci.com/us/en/st/newsearchpage?facetFilters=categoryLevel1_en%3AChildren&searchString=handbags&search-cat=header-search
So basically when the user clicks one of the algolia search suggestions(from the dropdown after clicking the search box at the top right corner of the page), they are taken to a search results page and there it seems like Algolia search is instantiated and displays the results.
Doubt 2:
How can I display the auto suggestions and product images side by side?
Doubt 3:
Displaying dynamic filter/refinement options. I understood that if there's a brand attribute in our Algoia indices/dataset, I can include that in the search filter like this:
<RefinementList attribute="brand" />
But if there are different attribute that I want to display the refinement list, say "Color", "Brand", etc. how would I display the title of the refinement option and the list dynamically from the search results.
Your UI example looks like a mash-up of a Query Suggestions panel on the left and a Hits list on the right. You can customize what a hit looks like before you render to get the image in there. And the filter menus automatically update as the user filters.
I haven't tried to get the query params into the URL, that would be interesting. I think you'd have to add useRouter into your Next page and then push the Algolia params onto the string using onClick.
Below is an example I built, maybe it helps you:
const Search = () => {
const Hit = ({ hit }) => {
return (
<HitContainer>
<span>{hit.type}</span>
<h2><a href={hit.path}>{hit.title}</a></h2>
{
hit.content &&
<p>{ `${hit.content.substring(0,150)} ...` }</p>
}
<hr />
</HitContainer>
)
}
return (
<>
<InstantSearch
searchClient={ AlgoliaReactClient }
indexName="MAINSITE" >
<CustomSearchBox
translations={{
submitTitle: 'Submit your search query.',
resetTitle: 'Clear your search query.',
placeholder: 'What are you looking for?',
}}
/>
<HitsAndFilters>
<AllFilters>
<h3>Topics</h3>
<FilterMenu
attribute="topics"
limit={5}
showMore
/>
<h3>Locations</h3>
<FilterMenu
attribute="locations"
limit={5}
showMore
/>
</AllFilters>
<AllHits hitComponent={Hit} />
</HitsAndFilters>
</InstantSearch>
</>
)
}
I am trying to add an onClick eventhandler into a material ui and sometimes it is called, sometimes it is not. However, it's working fine with regular buttons
handleClick = (event) => {
const value = event.target.value;
console.log(value);
this.setState({ filtered: this.state.videos.filter(item => {
return item.category === value
})
})
<Button value="java" onClick={this.handleClick} color="primary">Java</Button>
<Button value="React" onClick={this.handleClick} color="primary">React</Button>
<Button value="C#" onClick={this.handleClick} color="primary">C#</Button>
<Button value="javascript" onClick={this.handleClick} color="primary">JavaScript</Button>
when I updated to console.log to get event.target, I got the result shown in the image below
I found the issue, but still don't know how yo fix it. React adds two spans to the Button that have no attribute name, so when I click the button, the function gets called, but not when I click the span
You can use event.currentTarget.value instead of event.target.value.
Material-ui's Button has a nested span inside the button, so when you use event.target.value and the user clicks the span you get the span as event.target, if you'd use event.currentTarget you'd get the element that the event listener is attached to - the button.
See a working example: https://codesandbox.io/s/cocky-cookies-s5moo?file=/src/App.js
Inside your handle click, you could also do:
return (item.category === value || item.category === event.target.innerHTML)
But obviously CD..’s answer is better
Besides relying on currentTarget, you can always curry the parameter to the callback function (imagine you are not passing in static content, but maybe the index of an iteration or some dynamic values stored in an object, etc)
Example
handleClick = (value) => () => {
console.log(value);
this.setState({ filtered: this.state.videos.filter(item => {
return item.category === value
})
})
<Button value="java" onClick={this.handleClick('java')} color="primary">Java</Button>
<Button value="React" onClick={this.handleClick('React')} color="primary">React</Button>
<Button value="C#" onClick={this.handleClick('C#')} color="primary">C#</Button>
<Button value="javascript" onClick={this.handleClick('javascript')} color="primary">JavaScript</Button>
Although you don t need to look at the code below to understand the question, I added it in case you need to visualize the scenario. Whenever the form submits, addList method is called.
And the component updates itself. But I didn t expect this behaviour, that s why at first I did try to assign my lists to state, so that when the state changed the component would update itself as I wanted.
Anyway it already updates itself, but why ? Which way is more efficient ?
import React,{Component} from 'react';
import TrackerReact from 'meteor/ultimatejs:tracker-react';
import {Lists} from '../lib/collections/lists.js';
export default class App extends TrackerReact(Component) {
constructor(){
super();
// this.state = {lists : this.lists()}
}
lists(){
return Lists.find().fetch();
}
addList(e){
e.preventDefault();
//let text = this.refs.list.value ;
let text = this._inputList.value ;
console.log(this._inputList.value);
Lists.insert({
title : text
});
this._inputList.value = "";
//this.setState({lists : this.lists()});
}
render() {
return (
<div>
<h2>Lists</h2>
<ul>
{this.lists().map((a,b)=>(
<List key={a._id} title={a.title} />
))}
</ul>
<form onSubmit={this.addList.bind(this)}>
<input
type="text"
ref={(input)=>{
this._inputList = input ;
}}
placeholder="add list bro"
/>
</form>
</div>
)
}
}
So if we add a componentWillUpdate react life-cycle method to see if it rerenders ;
componentWillUpdate() {
console.log('will update');
}
When form submitted "will update" is logged on console as expected. However if we update addList as ;
addList(e){
e.preventDefault();
// nothing else.
}
We don t see the output "will update" on console. Which means method being called doesn t require the component to be rerendered. There is no such a rule. In this case , it is probably about TrackerReact. TrackerReact might force the component to rerender.