How to style a class based component on react-admin? - react-admin

Ive been looking for styling guides for react-admin, using material-ui. But I could not find an example on how it is done for class based components.
I hope someone shares their knowledge.
Thank you in advance.

user2002500. I hope this can help you.
1st, u need to import wtihStyles
import { withStyles } from '#material-ui/core/styles';
2nd, create a variable above class
const styles = {
field: {
widht: '80%' }
}
class Test extends Component {
....
}
3rd, add {...this.props} to a component you want to style
<TextField source= "id" {...this.props}/>
4th, add withStyles when export default
export default withStyles(styles)(Test)
5th, destructuring classes from this.props
render() {
const { classes } = this.props
return(
....
)
}
6th, last finishing back to the component you have add {...this.props},
add className property with classes.image
<TextField source= "id" className={classes.field} {...this.props}/>
Example:
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import { TextField, Edit, SimpleForm } from 'react-admin';
const styles = {
field: {
widht: '80%' }
}
class Test extends Component {
render() {
const { classes } = this.props
return (
<Edit title={'Test'} {...this.props}>
<SimpleForm>
<TextField source= "id" className={classes.field} {...this.props}/>
</SimpleForm>
</Edit>
);
}
}
export default withStyles(styles)(Test)
maybe, this not a good explanation. But i think this the right step if you want use class component then function component.

Related

Getting data from reducer into FlatList component

My code is working but I don't understand how "library" and library.id works in the keyExtractor. How library.id get id of the items from "libraries" reducer?
And also "library" in renderItem(library) and "library" in keyExtractor are same?
I would appreciate if anybody can shortly explain this.
import React, { Component } from 'react';
import { FlatList } from 'react-native';
import { connect } from 'react-redux';
import ListItem from './ListItem';
class LibraryList extends Component {
renderItem(library) {
return <ListItem library={library} />;
}
render() {
return (
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={library => library.id}
/>
);
}
}
const mapStateToProps = state => {
return { libraries: state.libraries };
};
export default connect(mapStateToProps)(LibraryList);
library (can be named anything) in your renderItem is coming from your
data={this.props.libraries}
renderItem(library) {
return <ListItem library={library} />;
}
this.props.libraries is coming from redux
- the key name `libraries` can be named anything other than `libraries`
- state.libraries is coming from your redux reducer (check your root reducer)
const mapStateToProps = state => {
return { libraries: state.libraries };
};
this is extracting the key id from your data which is coming from data={this.props.libraries}
keyExtractor={library => library.id}

How to get root component to re-render in react-native with redux (Open source project)

How would you get the root component in React-Native (Expo.io) to re-render on state change when using redux?
I'm trying to get <FormattedWrapper locale='en' messages={messages}> to update "locale" when state is changed.
I have tried to have a local state in the constructor, use store.getState().language.language, have a local variable which got update in ComponentWillUpdate because of a subscribe function from redux, but nothing works.
I have clean it all up and made a PR to the repo I want to contribute to: https://github.com/ipeedy/react-native-boilerplate/pull/3
The App.js code is here:
import React, { Component } from 'react';
import { StatusBar, Platform } from 'react-native';
import { Provider } from 'react-redux';
import { ThemeProvider } from 'styled-components';
import styled from 'styled-components/native';
import { FormattedWrapper } from 'react-native-globalize';
import messages from './Messages';
import store from './store';
import Navigator from './Navigator';
import { colors } from './utils/constants';
const Root = styled.View`
flex: 1;
background-color: ${props => props.theme.PINK_50};
`;
const StatusBarAndroid = styled.View`
height: 24;
background-color: ${props => props.theme.PINK_200};
`;
class App extends Component {
render() {
return (
<Provider store={store}>
<ThemeProvider theme={colors}>
<FormattedWrapper locale='en' messages={messages}>
<Root>
<StatusBar barStyle='light-content' backgroundColor='transparent' translucent />
{ Platform.OS === 'android' && Platform.Version >= 20 ? <StatusBarAndroid /> : null }
<Navigator />
</Root>
</FormattedWrapper>
</ThemeProvider>
</Provider>
);
}
}
export default App;
Thanks in advance for any help! :)
Since you're aleady using react-redux, therefore you can use the connect function of the same library.
Since Connect requires a new instance of the component that you are using, therefore it can be done as shown below.
First you need to make a separate component of what's inside your provider and connect it with the store
For example from what I understand in your code
import { Provider, connect } from 'react-redux';
class RootContainer extends Component {
render() {
const {locale} = this.props
return (
<ThemeProvider theme={colors}>
<FormattedWrapper locale={locale} messages={messages}>
<Root>
<StatusBar barStyle='light-content' backgroundColor='transparent' translucent />
{ Platform.OS === 'android' && Platform.Version >= 20 ? <StatusBarAndroid /> : null }
<Navigator />
</Root>
</FormattedWrapper>
</ThemeProvider>
);
}
}
const mapState = state = ({
locale: state.language.language
})
ConnectedRootContainer = connect(mapState, null)(RootContainer);
class App extends Component {
render() {
return (
<Provider store={store}>
<ConnectedRootContainer/>
</Provider>
);
}
}
export default App;
Or another simple way would be just to make the connected component for the <FormattedWrapper/>

react native pass props to another component

I've been struggling passing a value from one component to another. It's a continuation of the issue from a previous question which was partially resolved: react-native tab navigator search box
I'm using tab navigator and here's my app setup:
index.js (renders tab setup)
  router.js
     searchHeader.js
     tab1.js
     tab2.js
     etc
In index.js when a tab is changed I'm getting the name of the tab. I want to pass that to searchHeader.js to update the placeholder text.
As searchHeader.js isn't imported into index.js and not a direct child how do I pass it that value?
index.js
import React, { Component } from 'react';
import { Root, Tabs } from './config/router';
import { Alert,View } from 'react-native';
class App extends Component {
constructor(props) {
super(props);
this.state = {
searchText: '',
}
}
_getCurrentRouteName(navState) {
if (navState.hasOwnProperty('index')) {
this._getCurrentRouteName(navState.routes[navState.index])
} else {
if (navState.routeName==='One') {
this.setState({searchText:'Search One'})
}
if (navState.routeName==='Two') {
this.setState({searchText:'Search Two'})
}
if (navState.routeName==='Three') {
this.setState({searchText:'Search Three'})
}
if (navState.routeName==='Four') {
this.setState({searchText:'Search Four'})
}
}
}
render() {
return (
<Root onNavigationStateChange={(prevState, newState) => {
this._getCurrentRouteName(newState)
}} />
)
}
}
export default App;
router.js
...
export const Root = StackNavigator({
Tabs: {
screen: Tabs,
navigationOptions: {
header: <SearchHeader data={'Test'} />
}
},
}, {
mode: 'modal',
});
searchHeader.js
import React, { Component } from 'react';
import { View,Text,Dimensions,Alert } from 'react-native';
import { SearchBar } from 'react-native-elements';
class SearchHeader extends Component {
constructor(props) {
super(props);
this.state = {
placeholder: "Search One"
}
}
render() {
return (
<SearchBar
noIcon
containerStyle={{backgroundColor:'#fff'}}
inputStyle={{backgroundColor:'#e3e3e3',}}
lightTheme = {true}
round = {true}
placeholder={data}
placeholderTextColor = '#000'
/>
);
}
};
export default SearchHeader;
You could perhaps pass it as a navigation prop using the setParams method.
An alternative, depending on the scope of your app, would be to look at a state library such as Redux or MobX - but if it's a small app, it's overkill
For that you can use Redux, you will have a store where you can put shared properties and values,
Then your components can connect to that store and bind its props with the chosen reducer(s) and dispatch actions..
this structure may work:
class Home extends Component {
func(val) {
this.setState({value: val});
}
render() {
return (
<View>
<Two func={(val) => this.func(val)} />
</View>
)
}
}
class Two extends Component {
render() {
return (
<View>
<Button title="set" onPress={() => this.props.func('data')} />
</View>
)
}
}

MobX with React Native: store is undefined

This is my first go at using MobX so this may be a simpler problem than I imagine, but I'm not getting any errors with the things I've tried; the store is simply undefined wherever I try to use it. I've tried both importing the store directly into components and passing props from the main file (also with , but I'm not sure if I used that right). I've experimented with several different .babelrc file settings as well, but that doesn't seem to be an issue.
Here is the UserStore:
import React from 'react';
import { observable } from 'mobx';
class UserStore {
#observable info = {
username: "bob",
password: "secret",
email: "bob#email.com"
}
}
const userStore = new UserStore()
export default userStore;
Here is a simplified App.js:
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Profile from './app/Profile.js';
import { UserStore } from './app/UserStore.js';
export default class App extends Component {
constructor(){
super();
this.state = {
page: 'Profile',
}
}
changePage(){
switch (this.state.page) {
case "Profile":
return <Profile logout={this.logout.bind(this)} userStore={UserStore}/>;
}
}
render() {
return (
<View>
{this.changePage()}
</View>
);
}
}
And here is a simplified Profile.js:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { observer } from 'mobx-react/native';
#observer
export default class Profile extends Component {
render() {
console.log(this.props.userStore);
return (
<View>
<Text>Profile Page</Text>
<Text>username: {props from store go here}</Text>
<Text>password: {props from store go here}</Text>
<Text>email: {props from store go here}</Text>
</View>
);
}
}
All I'm trying to do right now is get the pre-defined observable "info" object from the store to the Profile.js component and display that information. This is being way more difficult than it should be - any insight is greatly appreciated!
Since you declared export default userStore; in UserStore.js
Try changing the way you import in App.js by removing the {}:
import UserStore from './app/UserStore.js';
{} is needed only if you want to do a named import. Here is a good read if you want to know more.

Call child function from parent component in React Native

I'm developing my first React Native app. What I'm trying to achieve is to execute a child function from the parent component, this is the situation:
Child
export default class Child extends Component {
...
myfunct: function() {
console.log('Managed!');
}
...
render(){
return(
<Listview
...
/>
);
}
}
Parent
export default class Parent extends Component {
...
execChildFunct: function() {
...
//launch child function "myfunct"
...
//do other stuff
}
render(){
return(
<View>
<Button onPress={this.execChildFunct} />
<Child {...this.props} />
</View>);
}
}
In this example, I would like to log 'Managed!' when I press the button in the parent class. How is it feasible?
Nader Dabit's answer is outdated, since using String literals in ref attributes has been deprecated. This is how we would do it as of September 2017:
<Child ref={child => {this.child = child}} {...this.props} />
<Button onPress={this.child.myfunc} />
Same functionality, but instead of using a String to reference the component, we store it in a global variable instead.
Here's how you can do this with functional components:
Parent
Use useRef() to give the child component a reference in the parent:
const childRef = useRef()
// ...
return (
<ChildComponent ref={childRef} />
)
...
Child
Pass ref as one of the constructor parameters:
const ChildComponent = (props, ref) => {
// ...
}
Import useImperativeHandle and forwardRef methods from the 'react' library:
import React, { useImperativeHandle, forwardRef } from 'react'
Use useImperativeHandle to bind functions to the ref object, which will make these functions accessible to the parent
These methods won't be internally available, so you may want to use them to call internal methods.
const ChildComponent = (props, ref) => {
//...
useImperativeHandle(ref, () => ({
// each key is connected to `ref` as a method name
// they can execute code directly, or call a local method
method1: () => { localMethod1() },
method2: () => { console.log("Remote method 2 executed") }
}))
//...
// These are local methods, they are not seen by `ref`,
const localMethod1 = () => {
console.log("Method 1 executed")
}
// ..
}
Export the child component using forwardRef:
const ChildComponent = (props, ref) => {
// ...
}
export default forwardRef(ChildComponent)
Putting it all together
Child Component
import React, { useImperativeHandle, forwardRef } from 'react';
import { View } from 'react-native'
const ChildComponent = (props, ref) => {
useImperativeHandle(ref, () => ({
// methods connected to `ref`
sayHi: () => { sayHi() }
}))
// internal method
const sayHi = () => {
console.log("Hello")
}
return (
<View />
);
}
export default forwardRef(ChildComponent)
Parent Component
import React, { useRef } from 'react';
import { Button, View } from 'react-native';
import ChildComponent from './components/ChildComponent';
const App = () => {
const childRef = useRef()
return (
<View>
<ChildComponent ref={childRef} />
<Button
onPress={() => {
childRef.current.sayHi()
}}
title="Execute Child Method"
/>
</View>
)
}
export default App
There is an interactive demo of this on Expo Snacks:
https://snack.expo.dev/#backupbrain/calling-functions-from-other-components
This explanation is modified from this TutorialsPoint article
You can add a ref to the child component:
<Child ref='child' {...this.props} />
Then call the method on the child like this:
<Button onPress={this.refs.child.myfunc} />
it is in react. i hope it may help you.
class Child extends React.Component {
componentDidMount() {
this.props.onRef(this)
}
componentWillUnmount() {
this.props.onRef(null)
}
method() {
console.log('do stuff')
}
render() {
return <h1>Hello World!</h1>
}
}
class EnhancedChild extends React.Component {
render() {
return <Child {...this.props} />
}
}
class Parent extends React.Component {
onClick = () => {
this.child.method() // do stuff
};
render() {
return (
<div>
<EnhancedChild onRef={ref => (this.child = ref)} />
<button onClick={this.onClick}>Child.method()</button>
</div>
);
}
}
ReactDOM.render(<Parent />, document.getElementById('root'))
Original Solution:
https://jsfiddle.net/frenzzy/z9c46qtv/
https://github.com/kriasoft/react-starter-kit/issues/909
Simple and easy way to Parent --> Child function call
/* Parent.js */
import React, { Component } from "react";
import { TouchableOpacity, Text } from "react-native";
import Child from "./Child";
class Parent extends React.Component {
onChildClick = () => {
this.child.childFunction(); // do stuff
};
render() {
return (
<div>
<Child onRef={(ref) => (this.child = ref)} />
<TouchableOpacity onClick={this.onChildClick}>
<Text>Child</Text>
</TouchableOpacity>
</div>
);
}
}
/* Child.js */
import React, { Component } from "react";
class Child extends React.Component {
componentDidMount() {
this.props.onRef(this);
}
componentWillUnmount() {
this.props.onRef(undefined);
}
childFunction() {
// do stuff
alert("childFunction called");
}
render() {
return <View>Hello World!</View>;
}
}
Original Solution:
https://github.com/kriasoft/react-starter-kit/issues/909
I think you have misunderstood something about component structure.
Assume that your child is a component which generates button for your other components. In this hierarchy your child has to inform it's parent that it was pressed.
child -----> parent
export default class Child extends Component {
return(
<Button onPress={this.props.onPress } />
);
}
In your parent component use child component to generate a button for you. In this way you can use child component any other components as a independent button.
export default class Parent extends Component {
constructor(props) {
super(props);
this.execChildFunct=this.execChildFunct.bind(this)
}
execChildFunct: function() {
console.log('Managed!');
}
return (
<Child onPress = {this.execChildFunct}></Child>
)
}