I recently started to learn React-Native and I was trying to implement React-Navigation V2 in one of my project but it does not seem to work. The project also uses Redux and other dependencies along with the core installed by Expo.
This is the code for my Router component that manages the Navigation:
import { createStackNavigator } from 'react-navigation';
import Movie from './Movie';
import Home from './Home';
const RoutRouter = createStackNavigator({
Movie : {
screen : Movie
},
Home : {
screen : Home
}
}, {
initialRouteName : 'Home'
});
export default RoutRouter;
Home Component
import React, { Component } from 'react';
import { View, Text, Button } from 'react-native';
class Home extends Component {
render() {
console.log('Home screen');
return (
<View>
<Text>HOME</Text>
</View>
);
}
}
export default Home;
Movie Component
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { View, Text, Button } from 'react-native';
import { apiRequest } from '../actions';
import { MOVIE } from '../constants';
class Movie extends Component {
//api request to retrieve data
getData = () => {
console.log('Button works!');
}
render() {
console.log('Movie screen');
return (
<View>
<Text>MOVIE</Text>
<Button title = 'Get Movie' onPress = {()=> {this.getData()}} />
</View>
);
}
}
const mapStateToProps = (state) => {
return{
state : state
}
}
export default connect(mapStateToProps, {apiRequest})(Movie);
Main Component
import React from 'react';
import { Provider } from 'react-redux';
import { StyleSheet, Text, View, Button, SafeAreaView } from 'react-native';
import store from './src/store';
import RootRouter from './src/routes/Router';
import { Constants } from 'expo';
console.ignoredYellowBox = ['Remote debugger'];
export default class App extends React.Component {
render() {
console.log('stae');
return (
<Provider store = { store }>
<SafeAreaView>
<View style={styles.container}>
<RootRouter />
</View>
</SafeAreaView>
</Provider>
);
}
}
const styles = StyleSheet.create({
container: {
marginTop: Constants.statusBarHeight,
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
and this is my package.json
{
"name": "m",
"version": "0.1.0",
"private": true,
"devDependencies": {
"jest-expo": "~27.0.0",
"react-native-scripts": "1.14.0",
"react-test-renderer": "16.3.1"
},
"main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"scripts": {
"start": "react-native-scripts start",
"eject": "react-native-scripts eject",
"android": "react-native-scripts android",
"ios": "react-native-scripts ios",
"test": "jest"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"axios": "^0.18.0",
"expo": "^27.0.1",
"react": "16.3.1",
"react-native": "~0.55.2",
"react-navigation": "^2.11.2",
"react-redux": "^5.0.7",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0"
}
}
At first I thought I was getting error but then when I logged the screen out I noticed that on the debugger the screen message is shown but the screen is blank.
Any idea what am I missing?
Related
I have a next.js project with custom 500.tsx file. When I throw an error in getServerSideProps my custom error page is shown few seconds, then Application error: a client-side exception has occurred (see the browser console for more information) default message shown. If I remove getInitialProps in my _app.tsx, then it works ok. So, how to make 500-error page and getInitialProps work together?
_app.tsx
import '../styles/globals.css';
import type { AppProps } from 'next/app';
import ErrorBoundary from '../components/error-boundary';
function MyApp({ Component, pageProps }: AppProps) {
const { lang } = pageProps;
return (
<ErrorBoundary>
<div>{lang}</div>
<Component {...pageProps} />
</ErrorBoundary>
);
}
MyApp.getInitialProps = async () => {
return {
pageProps: {
lang: 'en',
},
};
};
export default MyApp;
index.tsx
import type { GetServerSideProps, NextPage } from 'next';
const Home: NextPage = () => {
return (
<div>
<h1>Home</h1>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async ({ res }) => {
res.statusCode = 500;
throw new Error('Server error');
};
export default Home;
components/error-boundary.tsx
import { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children?: ReactNode;
}
interface State {
hasError: boolean;
}
class ErrorBoundary extends Component<Props, State> {
public state: State = {
hasError: false,
};
public static getDerivedStateFromError(_: Error): State {
return { hasError: true };
}
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Uncaught error:', error, errorInfo);
}
public render() {
if (this.state.hasError) {
return <h1>Sorry.. there was an error</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
package.json
{
"name": "error",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "12.2.2",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"#types/node": "18.0.5",
"#types/react": "18.0.15",
"#types/react-dom": "18.0.6",
"eslint": "8.19.0",
"eslint-config-next": "12.2.2",
"typescript": "4.7.4"
}
}
I'm trying to build a React Native app with Redux-thunk
I built the action and the reducer and I created the porvider and store and I called the action inside the useEffect in the component.
The problem: The problem is that the data does not reach the slider component, so I put the console.log("before async function") in the action, The console prints the log.
But when I put the console.log("inside async function"), Console does not print
Please help with the solution, thank you
package.json
{
"name": "rawamovies",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"axios": "^0.24.0",
"react": "17.0.2",
"react-native": "0.66.4",
"react-redux": "^7.2.6",
"redux-thunk": "^2.4.1"
},
"devDependencies": {
"#babel/core": "^7.16.7",
"#babel/runtime": "^7.16.7",
"#react-native-community/eslint-config": "^3.0.1",
"babel-jest": "^27.4.6",
"eslint": "^8.6.0",
"jest": "^27.4.7",
"metro-react-native-babel-preset": "^0.66.2",
"react-test-renderer": "17.0.2"
},
"jest": {
"preset": "react-native"
}
}
app.js
import React from 'react';
import {SafeAreaView, StyleSheet, Text, View} from 'react-native';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import {applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import {compainReducers} from './Redux/Reducer/CombainReducer';
import {Home} from './Screens/Home';
//start create redux store
const store = createStore(compainReducers, applyMiddleware(thunk));
//end create redux store
const App = () => {
return (
<Provider store={store}>
<View>
<Home></Home>
<Text>sss</Text>
</View>
</Provider>
);
};
export default App;
action.js
import {
POPULAR_MOVIES_REQUEST,
POPULAR_MOVIES_FAIL,
POPULAR_MOVIES_SUCCESS,
} from '../constents/getMovieconstents';
import axios from 'axios';
const KEY_V3 = '8ce99c09a3e30f614c';
const initURL = 'https://api.themoviedb.org/3';
export const popularMoviesAction = (pageNum = 1) => {
console.log('before async function');
return async dispatch => {
console.log("inside async function")
dispatch({action: POPULAR_MOVIES_REQUEST});
try {
const popularMovies = await axios.get(
`${initURL}/movie/popular?api_key=${KEY_V3}&page=${pageNum}`,
);
dispatch({action: POPULAR_MOVIES_SUCCESS, payload: popularMovies});
} catch (err) {
dispatch({action: POPULAR_MOVIES_FAIL, payload: err});
}
};
};
reducer.js
import {
POPULAR_MOVIES_REQUEST,
POPULAR_MOVIES_FAIL,
POPULAR_MOVIES_SUCCESS,
} from '../constents/getMovieconstents';
export const themeReducer = (state = false, action) => {
return state;
};
const initPopularMovies = {popularMovies: [], Loading: false, error: ''};
export const popularMoviesReducer = (state = initPopularMovies, action) => {
switch (action) {
case POPULAR_MOVIES_REQUEST:
return {...state, Loading: true};
case POPULAR_MOVIES_SUCCESS:
return {...state, popularMovies: action.payload, Loading: false};
case POPULAR_MOVIES_FAIL:
return {...state, error: action.payload, Loading: false};
}
return state;
};
slider.js component
import React, {useEffect} from 'react';
import {Text, View} from 'react-native';
import {popularMoviesAction} from '../Redux/Actions/GetDataAction';
import {useSelector} from 'react-redux';
export function Slider() {
const state = useSelector(state => state.popularMovies);
console.log('fetch data', state);
useEffect(() => {
popularMoviesAction();
}, []);
return (
<View>
<Text></Text>
</View>
);
}
enter image description here
You need to dispatch it, like
useEffect(() => {
dispatch(popularMoviesAction());
}, []);
So i'm building a design system for this company and the component system is displayed correctly in the design system storybook. But when I import it in the consumer app I get the following error
TypeError: Cannot read property 'width' of undefined in theme.border.width
Design System project:
/// src/components/Button/index.js
import { Wrapper } from './styles'
import React from 'react'
export const Button = (props) => (
<Wrapper {...props}>
{children}
</Wrapper>
)
.
///src/components/Button/styles.js
export const Wrapper = styled.button`
...
border-width: ${({theme}) => theme.border.width};
...
`
.
/// .storybook/preview.js
import React from 'react'
import { ThemeProvider } from 'styled-components'
import { GlobalStyle } from '../src/styles/globalStyles'
import { theme } from '../src/styles/theme'
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' }
}
export const decorators = [
Story => (
<ThemeProvider theme={theme}>
<GlobalStyle />
<Story />
</ThemeProvider>
)
]
.
/// src/index.js
...
export { Button } from 'components/Button'
export { theme } from 'style/theme'
...
.
/// babel.config.js
module.exports = {
presets: [
[
'#babel/env',
{
modules: false
}
],
['#babel/preset-react']
],
plugins: [
[
'styled-components',
{
ssr: true,
displayName: true,
preprocess: false,
minify: false
}
]
]
}
.
///rollup.config.js
import babel from 'rollup-plugin-babel'
import includePaths from 'rollup-plugin-includepaths'
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
export default [
{
input: 'src/index.js',
output: [
{
name: 'rollup-tutorial',
file: 'dist/index.js',
format: 'es'
}
],
plugins: [
babel({
exclude: 'node_modules/**'
}),
includePaths({
paths: ['src'],
extensions: ['.js', '.json', '.html']
}),
peerDepsExternal()
]
}
]
.
/// package.json
{
"name": "design-system",
"main": "dist/index.js"
"files: ["dist"],
"scripts": {
...
"build": "rollup --config"
...
},
"devDependencies": {
"#babel/core": "^7.12.10",
"#babel/preset-react": "^7.12.10",
"#babel/preset-env": "^7.12.13",
"react": "17.0.1",
"react-dom": "17.0.1",
"rollup": "^2.38.4",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-includepaths": "^0.2.4",
"rollup-plugin-peer-deps-external": "^2.2.4",
"styled-components": "^5.2.1",
},
"peerDependencies": {
"prop-types": ">= 15.x.x",
"react": ">= 17.x.x",
"styled-components": ">= 5.x.x",
}
}
App consumer NextJs default config
/// .babelrc
{
"presets": ["next/babel"],
"env": {
"development": {
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true
}
]
]
},
"production": {
"presets": [
"next/babel"
],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": false
}
]
]
}
}
}
.
///package.json
{
...
"dependencies": {
...
"design-system": "../design-system/",
...
}
...
}
.
/// pages/_app.js
import { ThemeProvider } from 'styled-components'
import { theme } from 'design-system'
function MyApp({ Component, pageProps }) {
console.log(theme)
return (
<ThemeProvider theme={theme}>
<Component {...pageProps} />
</ThemeProvider>
)
}
.
///pages/index.js
import { Button } 'design-system'
export default function Home() {
return (
<Button />
)
}
Note:
The console.log(theme) prints the expected theme however the button doesnt have access to the theme provided by styled-components.
I guess i'm missing some important configurantion in babel rollup or something
Note 2:
I already tried wrapping up the components in withComponent HOC
the only working solution was the next piece of code
///pages/index.js
import { Button } 'design-system'
import { useTheme } 'styled-components'
export default function Home() {
const theme = useTheme()
return (
<Button theme={theme} />
)
}
But this loses the whole point of using context
Thanks in advance
I've had a similar issue when developing a component library using storybook and emotion/styled-components. The issue was that I was using the styled-components' ThemeProvider from the consumer app, as you did in your _app.js. The solution was to create and export a custom ThemeProvider on the component library, using the library's styled-component package, like so:
import { ThemeProvider } from 'styled-components'
import { theme as defaultTheme } from '../src/styles/theme'
const CustomThemeProvider = ({ theme = defaultTheme, children }) => (
<ThemeProvider theme={theme}>
{children}
</ThemeProvider>
)
export { CustomThemeProvider }
and then use in your consumer app
/// pages/_app.js
import { CustomThemeProvider, theme } from 'design-system'
function MyApp({ Component, pageProps }) {
console.log(theme)
return (
<CustomThemeProvider theme={theme}>
<Component {...pageProps} />
</CustomThemeProvider>
)
}
The styled-components FAQ suggests to not ship your styled-components along with your bundle. This resolved the above mentioned issue for me.
https://styled-components.com/docs/faqs#i-am-a-library-author-should-i-bundle-styledcomponents-with-my-library
On Fetching the Json data from remote url and while trying to render it via FlatList Component ,I am constantly getting Red-Screen with this error "incompatible receiver map required" .
I strongly guess it is related to android.
Json Response is coming properly as seen in react-logger.
I tried adding core-js : 2.5.2 in "resolutions" in package.json but still did not work.
HomeScreen.js
import React, { Component } from "react";
import {
Text,
View,
FlatList,
ActivityIndicator,
Platform
} from "react-native";
import { Button } from "native-base";
import { connect } from "react-redux";
import firebase from "react-native-firebase";
import { onSignOut } from "../Actions/AuthActions";
import { stringify } from "qs";
class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: []
};
}
static navigationOptions = {
header: null
};
componentDidMount() {
// Checking user Auth State
this.unsubscribe = firebase.auth().onAuthStateChanged(user => {
this.props.navigation.navigate(user ? "App" : "Auth");
});
// Fetching the list of workers from Remote Url
return fetch("https://api.myjson.com/bins/xyz")
.then(response => response.json())
.then(responseJson => {
this.setState(
{
isLoading: false,
dataSource: responseJson.workers
},
function() {
// In this block you can do something with new state.
}
);
})
.catch(error => {
console.error(error);
});
}
componentWillUnmount() {
if (this.unsubscribe) this.unsubscribe();
}
render() {
// First Loadf the activity indicator till the json data is not fetched
if (this.state.isLoading) {
return (
<View style={{ flex: 1, paddingTop: 20 }}>
<ActivityIndicator />
</View>
);
}
console.log(JSON.stringify(this.state.dataSource));
return (
<View style={styles.container}>
<FlatList>
data = {this.state.dataSource}
renderItem=
{({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item, index) => index}
</FlatList>
</View>
);
}
}
const styles = {
container: {
flex: 1,
alignItems: "center",
alignContent: "center",
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "center"
},
FlatListItemStyle: {
padding: 10,
fontSize: 18,
height: 44
}
};
package.json
{
"scripts": {
"start": "react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios"
},
"dependencies": {
"#babel/runtime": "^7.4.4",
"firebase": "^5.11.1",
"isomorphic-fetch": "^2.2.1",
"native-base": "^2.12.1",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-native": "0.57.5",
"react-native-elements": "^1.1.0",
"react-native-firebase": "^5.3.1",
"react-native-gesture-handler": "^1.1.0",
"react-native-google-places-autocomplete": "^1.3.9",
"react-native-otp-inputs": "^2.0.1",
"react-native-phone-input": "^0.2.1",
"react-navigation": "^3.9.1",
"react-redux": "^5.0.7",
"redux": "^4.0.0",
"redux-immutable-state-invariant": "^2.1.0",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"babel-polyfill": "^6.26.0",
"babel-preset-expo": "^5.0.0",
"eslint-plugin-react-hooks": "^1.6.0",
"expo": "^32.0.6"
},
"resolutions": {
"core-js": "2.5.2"
},
"private": true
}
Error Should not come and items should be rendered accordingly.
Check your response first. Is it the right array like as [{name: 'a'}, {name: 'b"}]?
// Fetching the list of workers from Remote Url
return fetch("https://api.myjson.com/bins/xyz")
.then(response => response.json())
.then(responseJson => {
console.log(responseJson); // Check your response
this.setState(
{
isLoading: false,
dataSource: responseJson.workers
},
function() {
// In this block you can do something with new state.
}
);
})
.catch(error => {
console.error(error);
});
}
Update
You used flatlist to wrong way.
<FlatList>
data = {this.state.dataSource}
renderItem=
{({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item, index) => index}
</FlatList>
need to change below
<FlatList
data={this.state.datasource}
renderItem={...}
/>
I know this question may have been asked but am just frustrated. Reactjs marks = at the line of code below as unexpected token error
handleChange1 = {(selectedOption) => {
All the required dependency has been installed.
below is the entire code
import React, { Component } from 'react';
import { render } from 'react-dom';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import Hello from './Hello';
import Select from 'react-select'
//import './style.css';
import 'react-select/dist/react-select.css';
class Plans extends Component {
constructor() {
super();
this.state = {
name: 'React',
selectedOption: {},
selectedOption2: {}
};
}
handleChange1 = {(selectedOption) => {
this.setState({selectedOption});
}
};
handleChange2 = (selectedOption) => {
this.setState({selectedOption2: selectedOption})
}
render() {
const options1 = [
{value: 'one', label: 'One'},
{value: 'two', label: 'Two'}
];
const options2 = [
{value: 'one-a', label: 'One A', link: 'one'},
{value: 'one-b', label: 'One B', link: 'one'},
{value: 'two-a', label: 'Two A', link: 'two'},
{value: 'two-b', label: 'Two B', link: 'two'}
];
const filteredOptions = options2.filter((o) => o.link === this.state.selectedOption.value)
return (
<div>
<p>Select one first</p>
<Select
name="form-field-name"
value={this.state.selectedOption.value}
onChange={this.handleChange1}
options={options1}
/>
<p>Then the other</p>
<Select
name="form-field-name"
value={this.state.selectedOption2.value}
onChange={this.handleChange2}
options={filteredOptions}
/>
</div>
);
}
}
//render(<Plans />, document.getElementById('app'));
function mapStateToProps(state) {
}
const connectedPlans = connect(mapStateToProps)(Plans);
export { connectedPlans as Plans };
Here is my package.json
{
"name": "example",
"version": "1.0.0",
"repository": {
"type": "git",
"url": ""
},
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --open"
},
"dependencies": {
"history": "^4.6.3",
"node-sass": "^4.9.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-redux": "^5.0.5",
"react-router-dom": "^4.1.2",
"react-select": "^2.1.1",
"react-toastify": "^4.4.0",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-3": "^6.24.1",
"css-loader": "^1.0.1",
"html-webpack-plugin": "^2.26.0",
"path": "^0.12.7",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.8.2"
}
}
Updates
App.jsx
import React from 'react';
import { Router, Route } from 'react-router-dom';
import { connect } from 'react-redux';
import { history } from '../_helpers';
import { alertActions } from '../_actions';
import { PrivateRoute } from '../_components';
import { Plans } from '../Plans';
class App extends React.Component {
constructor(props) {
super(props);
const { dispatch } = this.props;
history.listen((location, action) => {
// clear alert on location change
dispatch(alertActions.clear());
});
}
render() {
const { alert } = this.props;
return (
<div className="jumbotron">
<div className="container">
<div className="col-sm-8 col-sm-offset-2">
{alert.message &&
<div className={`alert ${alert.type}`}>{alert.message}</div>
}
<Router history={history}>
<div>
<Route path="/plans" component={Plans} />
</div>
</Router>
</div>
</div>
</div>
);
}
}
function mapStateToProps(state) {
const { alert } = state;
return {
alert
};
}
const connectedApp = connect(mapStateToProps)(App);
export { connectedApp as App };
How I solve the problem. First I implemented the solution powered by Dacre in the comments above. I then discovered that react-select.css' files is not in the node_modules so I re-install it again so as to enable me to import it..
I added this line of code below
render(<Plans />, document.getElementById('app'));
and then remove the code below
function mapStateToProps(state) {
}
const connectedPlans = connect(mapStateToProps)(Plans);
export { connectedPlans as Plans };