React : using props outside of render - javascript

I use the semantic tab components of the user interface in my project. I want to render dynamically tabs with tab items. But, I can’t call the props dialog outside the component to go through all the elements of the object and pass a property to Tab.Pane that will display the contents
const panes = dialogs.map((d, index) => ({
menuItem:
<Menu.Item key={index}>
<AppMessageUserList {...d} />
</Menu.Item>,
render: () =>
<Tab.Pane>
<AppMessageItems {...d} />
</Tab.Pane>
}));
Render:
const AppMessages = () => {
return (
<Container>
<Tab
menu={{fluid: true, vertical: true}}
menuPosition='left'
panes={panes}
/>
</Container>
);
};
Data from redux
function mapStateToProps(state) {
return {
dialogs: state.dialogs,
}
}

Related

Dialog of material UI has afterimage when being closed

Introduction
Bascially <Dialog /> receives open and onClose as props. open is boolean from state and onClose is a function that changes the state.
I made <CustomModal /> that wraps <Dialog />, which receives another prop content that defines what to display on <Dialog />.
// CustomModal.jsx
const CustomModal = props => (
<Dialog {...props} sx={{ '& .MuiDialog-paper': { padding: '2em' } }}>
{props.content}
</Dialog>
);
And I'm delivering handlers using context so that my modal could be open and closed everywhere.
// modalHandlersContext.js
const initialState = {
open: false,
content: null,
};
const ModalHandlersProvider = ({ children }) => {
const [modal, setModal] = useState(initialState);
const handlers = {
openModal: payload => setModal({ open: true, ...payload }),
closeModal: () => setModal(initialState),
};
return (
<ModalHandlersContext.Provider value={handlers}>
{children}
<CustomModal
open={modal.open}
onClose={handlers.closeModal}
content={modal.content}
></CustomModal>
</ModalHandlersContext.Provider>
);
};
When I want to open modal somewhere, I execute a function like this
const onLogin = () =>
openModal({
content: <h1>component</h1>,
});
That is, I pass a component. (I used h1 for a simple example)
Main subject
But when I close it, it's not clean.
I experimented on this to check when this happens.
It happens
With css, display something from props(same code as above)
const CustomModal = props => (
<Dialog {...props} sx={{ '& .MuiDialog-paper': { padding: '2em' } }}>
{props.content}
</Dialog>
);
It doesn't happen
Without css, display something from props
const CustomModal = props => (
<Dialog {...props}>
{props.content}
</Dialog>
);
2,3. With/Without css, display just plain text
const CustomModal = props => (
<Dialog {...props} sx={{ '& .MuiDialog-paper': { padding: '2em' } }}>
content
</Dialog>
);
const CustomModal = props => (
<Dialog {...props}>
content
</Dialog>
);
So after that, I tried using <DialogContent /> instead of css but It didn't work. But I have tried using <Modal /> instead of <Dialog /> and it hasn't caused any problems.
I wanna use <Dialog /> if possible but now can't find the cause.
Can anyone help?

How to build a generic menu component?

I have to build a menu screen component that can be used later on easily. The component only has options in a list way.
const options = [
{
text: 'Option 1',
},
{
text: 'Option 2',
},
{
text: 'Option 3',
},
];
and I just map it inside the component.
const Menu = () => {
return (
<div>
{options.map((option, index) => (
<MenuOption text={option.text} index={index} />
))}
</div>
);
};
const MenuOption = ({ text, index }) => {
return (
<div>
<p>{text}</p>
</div>
);
};
So anyone can use this menu component by passing in the options data. What i want is for this component to also run functions corresponding to the option clicked. So we can easily pass the function that needs to be run as a prop to the component. The main question is that how do i relate/map the options with the corresponding function?
NOTE: I can't send the functions with the options data object in the props.
I mean you can just send one callback to the Menu component:
const Menu = ({ onOptionClick }) => {
return (
<div>
{options.map((option, index) => (
<MenuOption text={option.text} index={index} onClick={onOptionClick} />
))}
</div>
);
};
const MenuOption = ({ text, index, onClick }) => {
return (
<div onClick={() => { onClick(index, text, whatever) }}>
<p>{text}</p>
</div>
);
};

How to control of open/close modal in react-native

I want to control of 'Opening and Closing Modals' without using Redux. If I use Redux, i create a variable as isVisible and control it with setting a value as true or false. But, If I dont use Redux, i cant solve problem that explained below.
It's the code that I call modal function.
<TouchableOpacity onPress={ () => this.setState({ visibleModal: true ])}>
<Text> Press me! </Text> </TouchableOpacity>
<ProfileModals isVisible={this.state.visibleModal} />
Main Modal function:
export default class ProfileModals extends Component {
state = {
visibleModal: this.props.isVisible,
modal: "changeName"
};
render() {
const {visibleModal} = this.state;
return (
<Modal
isVisible={this.state.visibleModal}
backdropColor="black"
backdropOpacity={0.5}
animationOut="fadeOut"
onBackdropPress={() => this.setState({ visibleModal: false })}
swipeDirection={"down"}
onSwipeComplete={() => this.setState({ visibleModal: false })}
>
<View>
<Text>Hello!</Text>
</View>
</Modal>
);
}
}
When I press the button at the first time, Modal run correctly. After closing the modal, I press the button second time, It doesn't run anymore. Because of this.state.visibleModal value (in ProfileModal Component) is false, not this.props.isVisible.
How can i solve this problem?
dont store the modal's visibility in the state of the modal component, allow it to flow through props from the parent, follow this approach:
class Parent extends Component {
state = {
modalVisible: false,
};
openModal = () => this.setState({ modalVisible: true });
closeModal = () => this.setState({ modalVisible: false });
render() {
const { modalVisible } = this.state;
return (
<OtherStuff>
<Button onPress={this.openModal} />
<MyModal
visible={modalVisible}
closeModal={this.closeModal}
/>
</OtherStuff>
);
}
}
class MyModal extends Component {
render() {
const { visible, closeModal } = this.props;
return (
<Modal isVisible={visible}>
<Button onPress={closeModal} />
</Modal>
);
}
}

Function components in react native

I am trying to change view of ListItem by pressing on it.
In My screen which is normal React component i have functional List component and selectedItemState (only 1 or no items will be selected).
In List there are few also functional ListItem components.
The problem is lack of re-render ability for item.
I've tried memo as official React page says but with no results. Changing components to normal ones gave the same result.
Screen Component:
export default class myScreen extends Component {
constructor () {
super ()
this.state = {
data: [], // <-- there are my objects
isDataEmpty: false,
selectedItemId: ''
}
}
// ... some code
render () {
return (
<View style={styles.container}>
<List
itemList={this.state.data}
onItemPress={ /* go to next screen */}
onItemLongPress={id => {
this.setState({ selectedItemId: this.state.selectedItemId === id ? '' : id })
}}
selectedItemId={this.state.selectedItemId}
/>
</View>
)
}
}
List Component:
const List = props => {
return (
<FlatList
style={style.itemList}
data={props.itemList}
renderItem={info => (
<ListItem
item={info.item}
selectedItemId={props.selectedItemId}
onItemPress={id => props.onItemPress(id)}
onItemLongPress={id => props.onItemLongPress(id)}
/>
)}
/>
)
}
const areEqual = (previous, next) => {
return next.selectedItemId !== '' && (previous.selectedItemId === next.selectedItemId)
}
export default React.memo(List, areEqual)
List Item Component:
const ListItem = props => {
return (
<TouchableWithoutFeedback
onPress={() => props.onItemPress(props.item.id)}
onLongPress={() => {
props.onItemLongPress(props.item.id)
} }>
<View style={style.listItem}>
<Image resizeMode='cover' source={props.item.image} style={style.image} />
<Text>{props.selectedItemId === props.item.id ? 'XXX' : props.item.name}</Text>
</View>
</TouchableWithoutFeedback>
)
}
const areEqual = (previous, next) => {
return next.selectedItemId && (next.selectedItemId === next.item.id)
}
export default React.memo(ListItem, areEqual)
After pressing on any item i want it name to change to 'XXX'. If item will be pressed twice all items should be in normal state
As long as there are no changes on the item itself there will be no rerender of the according listitem.
You could try to force a rerender of the list by changing the value of the extraData flatlist prop though.

Passing a component a navigation screen via props from screen component

I am building an app that has a list on the home screen routing to a number of other screens.
I created a list component that is rendered on the home page, and therefore, need to pass the navigation down to the list component. The list component, in turn, will determine which screen to display depending on which item is pressed.
I am using a Stack Navigator on my router.js file
export const HomeStack = StackNavigator({
Home: {
screen: Home,
navigationOptions: {
title: 'Home',
},
},
Nutrition: {
screen: Nutrition,
navigationOptions: {
title: 'Nutrition',
}
},
});
In my home.js screen I have the below code inside the render method
render() {
return (
<View>
<View>
<ListComponent navigate={this.props.navigation.navigate('')} />
<Button
title="Go to Nutrition"
onPress={() => this.props.navigation.navigate('Nutrition')}
/>
</View>
</View>
);
}
The Button successfully routes to the Nutrition.js screen.
But, I try to get my ListComponent.js to handle where to route as this file maps through my list array.
render() {
return (
<List>
{ListData.map((listItem, i) => (
<ListItem
key={i}
title={listItem.title}
leftIcon={{ name: listItem.icon }}
onPress={this.onPressHandler(listItem.title)}
/>
))}
</List>
);
}
How can I properly pass the navigation as props down to ListComponent.js and then use the title from the list array to determine which screen to display?
change this line :
<ListComponent navigate={this.props.navigation.navigate('')} />
to this :
<ListComponent navigate={(screen)=>this.props.navigation.navigate(screen)}/>
and change this
<ListItem
key={i}
title={listItem.title}
leftIcon={{ name: listItem.icon }}
onPress={this.onPressHandler(listItem.title)}
/>
to this :-
<ListItem
key={i}
title={listItem.title}
leftIcon={{ name: listItem.icon }}
onPress={()=>this.props.navigate(listItem.title)}
/>
As you are calling the method directly not binding it to the component.
I am assuming that your code in ListItem.js is correct.

Categories

Resources