React-select Clear and Dropdown indicators order - react-select

Thank the author for this library, but i have one question:
How to change order of Clear and Dropdown indicators (i want: Dropdown - first, Clear - second)?
I know this indicators are in children prop, but how change order on render?
Or how I can add additional button for clear after Dropdown indicator?

ClearIndicator and DropdownIndicator both are children of the IndicatorsContainer so that would be where the updates would have to be made.
One approach would be to first render a DropdownIndicator, then loop through the IndicatorContainer's children to find the DropdownIndicator, and remove it.
import React, { Children } from "react";
import Select, { components } from "react-select";
const IndicatorsContainer = ({ children, ...props }) => {
const allowedChildren = Children.map(children, (child) => {
return (child && child.type.name !== 'DropdownIndicator') ? child : null;
});
return (
<components.IndicatorsContainer {...props}>
<components.DropdownIndicator />
{allowedChildren}
</components.IndicatorsContainer>
);
};
const CustomSelect = (props) => (
<Select components={{ IndicatorsContainer }} {...props} />
)
export default CustomSelect;
Note: I found this SO question from the react-select issues page here where the user asked to move the DropdownIndicator and IndicatorSeparator to the left of the input which is a bit more complex but has a working codesandbox solution.

Related

use React Hook in multi files?

Senario : I have a dialog, and i use a react-hook to make it disappear ,like const[show,setShow]= useState(false) , this dialog file is a seperate file with main screen file, which contain button to show this dialog
Problem : I don't know how to show this dialog in main screen, for example, my dialog file called Mydialog.js have componet Mydialog, so i tried to put that hook show in props , Mydialog(show), but look like it not work that way, i still can't show the dialog
Question. How can i use react-hook for multi file, like i have hook in dialog file, present the dialog status ( show or not) then i can use it in mainScreen file to set show to true, then i can use that show and set to false when click button in dialog
If I understood it right you're trying to bring up a dialog when you interact with something on the main page and then close it by clicking on the X within the dialog. Would something like this work?
Main.js:
import "./styles.css";
import { useState } from "react";
import MyDialog from "./MyDialog";
export default function App() {
const [showDialog, setShowDialog] = useState(false);
const handleDialog = () => {
setShowDialog(!showDialog);
};
return (
<>
<button onClick={handleDialog}>Show Dialog</button>
Show Dialog: {showDialog?.toString()}
{showDialog && <MyDialog handleDialog={handleDialog} />}
</>
);
}
MyDialog.js:
import "./styles.css";
export default function MyDialog({ handleDialog }) {
return (
<>
<div className="popup">
<div className="popup_open">
<h1>Dialog Content</h1>
<button onClick={handleDialog}>X</button>
</div>
</div>
</>
);
}
Sandbox link if you want to test: https://codesandbox.io/s/admiring-feather-sy1gf
You can use Context to maintain state between multiple components.
const DialogContext = createContext();
const DialogProvider = ({ children }) => {
const [isDialogVisible, setDialogVisible] = useState(false);
const value = {
isDialogVisible,
setDialogVisible,
}
return <DialogContext.Provider value={value}>{children}</DialogContext.Provider>
}
const useDialog = () => {
const context = useContext(DialogContext);
return context;
}
Render the DialogProvider in one of the top-level components, for example in App.js.
// App.js
return (
<DialogProvider>
// ...
</DialogProvider>
)
Then inside of your components you can use your hook and trigger the visibility of the dialog.
MyComponentA:
const { isDialogVisible, setDialogVisible } = useDialog();
const toggleDialogVisibility = () => {
setDialogVisible(!isDialogVisible);
}
return (
<Button title="Toggle" onPress={toggleDialogVisibility} />
)
MyComponentB:
const { isDialogVisible } = useDialog();
if(isDialogVisible) {
return <Text>My Dialog</Text>
}
return null;
A very simple example of usage, here's a Snack for the above.

React native flatlist rerender

I'm working on a flatlist that has complex child that cause expensive rerender, I need to optimize that but I'm not able to stop the rerendering with useMemo, please help me to go through this.
Here my list code:
<FlatList
data={thePosts}
extraData={thePosts}
keyExtractor={(item, index) => index.toString()}
removeClippedSubviews={true}
maxToRenderPerBatch={5}
updateCellsBatchingPeriod={30}
initialNumToRender={11}
windowSize={5}
refreshing={isRefreshing}
onRefresh={handleOnRefresh}
onEndReached={isLoading ? () => null : () => getPosts("more")}
onEndReachedThreshold={0.1}
renderItem={memoizedPost}
//renderItem={renderThePost}
ItemSeparatorComponent={renderThePostSep}
ListFooterComponent={renderThePostListFooter}
/>
here the renderPost:
const renderThePost = (props) => {
let post = props.item;
if (post[0].type == "share") {
return (
<TheSharedPost thePost={post} />
);
} else {
return <ThePost thePost={post} />;
}
};
I've tried to use memoization like this:
const memoizedPost = useMemo(() => renderThePost, []);
Now the problem is, the empty array as useMemo argument I think that only accept the first render but not working, I've tried to use [item.someProperty] but I'm not able to recognize item in the argument (item is not defined)
I've also used useCallback but still no luck, a lot o rerendering happen. Please help me to fix this. Tnz
you can use React.memo to avoid rendering of flatlist items
function TheSharedPost(props) {
/* render using props */
}
export default React.memo(TheSharedPost);
function ThePost(props) {
/* render using props */
}
export default React.memo(ThePost);

React-native Formik setFieldValue

Here is a simplified version of my code.
Notice the setFieldValue_ and this.setFieldValue_ = setFieldValue;
This code works fine, I'm able to get the output when submit button is clicked.
I'm actually wondering if this is the right way to do it? If not, can you point me to the right direction? Also what is this method called? (assigning class variable to some function and use it within another function)
class MyComponent extends React.Component {
setFieldValue_;
someFunction() {
this.setFieldValue_("name", value);
}
render() {
return (
<Formik
initialValues={{
something: ""
}}
onSubmit={values => console.log(values)}
>
{({
setFieldValue,
}) => {
this.setFieldValue_ = setFieldValue;
<ThirdPartyCustomComponent onChange={this.someFunction} />
}}
</Formik>
}
}
I would personally have the onChange simply call formik set field value there and then rather than using different functions. Strictly speaking you don't want to set the value like that because every re-render is setting the value again.
I would also recommend looking at custom formik inputs using the useField hook - https://jaredpalmer.com/formik/docs/api/useField. This will allow you to write a small wrapper around your third party component and formik. Noticing you have used a class based component you may want to do some short reading into react hooks before throwing yourself into using useField.
Docs example:
const MyTextField = ({ label, ...props }) => {
const [field, meta, helpers] = useField(props);
return (
<>
<label>
{label}
<input {...field} {...props} />
</label>
{meta.touched && meta.error ? (
<div className='error'>{meta.error}</div>
) : null}
</>
);
};

Pivot: Start with no tabs selected

Using Fabric React, I am working on a component that uses the Pivot element.
When the component is first shown, no tabs should be selected, and some content must be shown under the tab headers. Once a tab is clicked, related content will be shown there.
The example "No Pivots Selected" in the documentation page is pretty close to what I want. In the first render, no tabs are selected. I am thinking that the prop selectedKey={null} should give that result.
Following code is based on that example, yet even when the component is shown first time, a tab (first one) is shown as selected (e.g. there is a blue underline under it).
What is the problem?
import * as React from "react";
import { Pivot, PivotItem } from "office-ui-fabric-react";
export interface MainProps {}
export const Main: React.FC<MainProps> = () => {
const [selectedKey, setSelectedKey] = React.useState(null);
const pivotItems: { [key: string]: React.ReactElement<any> } = {
Settings: <div>Settings</div>,
Controls: <div>Controls</div>
};
const _getTabId = (itemKey: string): string => {
return `ShapeColorPivot_${itemKey}`;
};
const _handleLinkClick = (item: PivotItem): void => {
setSelectedKey(item.props.itemKey);
};
return (
<>
<Pivot
headersOnly
selectedKey={selectedKey}
getTabId={_getTabId}
onLinkClick={_handleLinkClick}
style={{ flexGrow: 1 }}
>
{Object.keys(pivotItems).map(name => (
<PivotItem
key={`pivotItemKey_${name}`}
headerText={name}
itemKey={name}
/>
))}
</Pivot>
{selectedKey ? pivotItems[selectedKey] : <div>Start</div>}
</>
);
};
I did a quick codepen using
<Pivot selectedKey={null} >
and it worked just fine. Are you sure you're on the most recent version of Fabric?

Is it OK to pass a lot of props to a child component (redux)

I have a component that has a child component within it.
This child component needs to access to the state, and dispatch a lot of actions. So I ended up having a component that takes all these properties through his own props.
render(){
const menu = <Menu
navigator={navigator}
userTracks={this.props.tracks}
currentTrackID={this.props.currentTrack.id}
onAddNewTrack={() => {this.props.addNewTrack()}}
onEditTrack={(track) => {this.props.onEditTrack(track)}}
onClearBeacons={(track) => {this.props.onClearBeacons(track)}}
onDeleteTrack={(track) => {this.props.onDeleteTrack(track)}}/>;
return(
<SideMenu
menu={menu}
isOpen={this.props.sideMenuOpened}
onChange={(state) => {this.props.changeSideMenuOpened(state)}}
menuPosition='right'>
...more stuff...
</SideMenu>
);
I rely a lot on this component, and it is highly probable that the list of props will keep on growing again and again.
Is there any cleaner way to access the store in a child component other than through props ?
Is it okay to do it this way ?
You can reduce the code in the following manner:
onClick(type, data) {
switch (type) {
case 'addNewTrack':
this.props.addNewTrack();
break;
case 'editTrack':
this.props.onEditTrack(data.track);
break;
case 'clearBeacons':
this.props.onClearBeacons(data.track);
break;
case 'deleteTrack':
this.props.onDeleteTrack(data.track);
break;
default:
break;
}
}
render() {
const menuProps = {
navigator: navigator,
userTracks: this.props.tracks,
currentTrackID: this.props.currentTrack.id,
onClick: this.onClick
}
const menu = <Menu {...menuProps} />
return (
<SideMenu
menu={menu}
isOpen={this.props.sideMenuOpened}
onChange={(state) => { this.props.changeSideMenuOpened(state) }}
menuPosition='right'>
...more stuff...
</SideMenu>
);
}
As you can see the data props are combined as an object and spread onto the <Menu /> component. For the multiple methods, I am only passing a single click. Menu component will send the type and data that each represents the various clicks.
Hope this helps :)