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"
}
}
Related
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());
}, []);
I'm attempting to use the modern Context API within React-Native, but I'm getting the following error:
TypeError: TypeError: undefined is not an object (evaluating
'Context._context')
my createDataContext.js:
import React, { useReducer } from 'react'
export default (reducer, actions, defaultValue) => {
const Context = React.createContext()
const Provider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, defaultValue)
const boundActions = {}
for (let key in actions) {
boundActions[key] = actions[key](dispatch)
}
return (
<Context.Provider value={{ state, ...boundActions }}>
{children}
</Context.Provider>
)
}
return { Context, Provider }
}
My context.js:
import { AsyncStorage } from 'react-native'
import createDataContext from './createDataContext'
import {
LOGIN_FIRST_STEP,
LOGIN_SECOND_STEP,
AUTH_MODAL,
SIGNIN_MODAL,
SIGNUP_MODAL,
} from '../constants'
const INITIAL_STATE = {
email: '',
firstName: '',
lastName: '',
password: '',
cardNumber: '',
expiration: '',
CVV: '',
billingAddress: '',
authOpen: false,
signupOpen: false,
signinOpen: false,
}
const reducer = (state = INITIAL_STATE, { type, payload }) => {
switch (type) {
case LOGIN_FIRST_STEP:
const { email, firstName, lastName, password } = payload
return {
...state,
email,
firstName,
lastName,
password,
}
case LOGIN_SECOND_STEP:
const { cardNumber, expiration, CVV, billingAddress } = payload
return {
...state,
email,
cardNumber,
expiration,
CVV,
billingAddress,
}
case AUTH_MODAL:
return {
...state,
authOpen: true,
signupOpen: false,
signinOpen: false,
}
case SIGNUP_MODAL:
return {
...state,
authOpen: false,
signupOpen: true,
signinOpen: false,
}
case SIGNIN_MODAL:
return {
...state,
authOpen: false,
signupOpen: false,
signinOpen: true,
}
default:
return state
}
}
const login = dispatch => values => {
dispatch({ type: LOGIN_FIRST_STEP, payload: values })
}
const login2 = dispatch => values => {
dispatch({ type: LOGIN_SECOND_STEP, payload: values })
}
const auth = disaptch => () => {
dipatch({ type: AUTH_MODAL })
}
const signin = disaptch => () => {
dipatch({ type: SIGNIN_MODAL })
}
const signup = disaptch => () => {
dipatch({ type: SIGNUP_MODAL })
}
export const { Provider, Context } = createDataContext(
reducer,
{ login, login2, auth, signin, signup },
{ authOpen: false , signinOpen: false, signupOpen: false }
)
package.json:
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"#apollo/react-hooks": "^3.1.1",
"apollo-cache-inmemory": "^1.6.3",
"apollo-client": "^2.6.4",
"apollo-link": "^1.2.13",
"apollo-link-error": "^1.1.12",
"apollo-link-http": "^1.5.16",
"apollo-link-state": "^0.4.2",
"apollo-link-ws": "^1.0.19",
"apollo-utilities": "^1.3.2",
"expo": "^34.0.1",
"formik": "^1.5.8",
"graphql": "^14.5.6",
"graphql-tag": "^2.10.1",
"react": "16.8.3",
"react-apollo": "^3.1.1",
"react-dom": "^16.9.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
"react-native-gesture-handler": "~1.3.0",
"react-native-maps": "~0.24.0",
"react-native-reanimated": "~1.1.0",
"react-native-web": "^0.11.4",
"react-navigation": "^4.0.6",
"react-navigation-stack": "^1.8.0",
"react-navigation-tabs": "^2.5.4",
"subscriptions-transport-ws": "^0.9.16",
"yup": "^0.27.0"
},
"devDependencies": {
"babel-preset-expo": "^6.0.0"
},
"private": true
}
And finally app.js:
export default App = () => {
return (
<ApolloProvider client={client}>
<ApolloHooksProvider client={client}>
<ContextProvider>
<Root />
</ContextProvider>
</ApolloHooksProvider>
</ApolloProvider>
)
}
When I attempt to use by importing Context and using the useContext hook:
const {
state,
authModal
} = useContext(Context)
the aforementioned error shows. I've tried removing the react-native package and re-installing it with the latest version. I've tried deleting the node modules, clearing the cache, and re-installing them, but none seem to solve the issue.
I had the same error and it's because I was importing Context like this:
import {Context} from '...'
INSTEAD OF
import Context from '..'
For me, it was as simple as... I forgot to add the Provider to my main (App.js) file.
Try this:
Suppose you have a DataContext.js
--
import React, {createContext} from 'react';
export const DataContext = createContext();
export default function DataProvider({children}) {
return (
<DataContext.Provider>
{children}
</DataContext.Provider>
);
};
Then, try to import them like this:
--
import your provider without curly braces And your context within curly braces;
--
import DataProvider from "./src/context/DataContext";
import {DataContext} from "./src/context/DataContext";
Or:
import DataProvider , {DataContext} from "./src/context/DataContext";
I've created an app using create-react-app, then used the official github instructions for integrating with React (v16.6.3):
import DirectLine from 'botframework-directlinejs';
import React from 'react';
import ReactWebChat from 'botframework-webchat';
export default class extends React.Component {
constructor(props) {
super(props);
this.directLine = new DirectLine({ token: 'YOUR_BOT_SECRET' });
}
render() {
return (
<ReactWebChat directLine={ this.directLine } />
element
);
}
}
However, I'm getting this error:
TypeError: botframework_directlinejs__WEBPACK_IMPORTED_MODULE_5___default.a is not a constructor
What am I missing here? Thanks!
Note, there is (at time of writing this) an error in the instructions in the official repo:
import DirectLine from 'botframework-directlinejs';
should be:
import { DirectLine } from 'botframework-directlinejs';
Change this, and botframework-webchat v4 works with React 16, with the instructions on the github page.
If you want to use v3 of botframework-webchat, the following code worked for me:
After some experimenting and digging in other repos, here's how I was able to do this using a clean create-react-app instance:
in /src/App.js:
import React, { Component } from 'react';
import * as WebChat from 'botframework-webchat';
class App extends Component {
constructor(props) {
super(props);
this.state = { token: null };
}
async componentDidMount() {
const myHeaders = new Headers()
var myToken = process.env.REACT_APP_DIRECTLINE_SECRET
myHeaders.append('Authorization', 'Bearer ' + myToken)
const res = await fetch(
'https://directline.botframework.com/v3/directline/tokens/generate',
{
method: 'POST',
headers: myHeaders
}
)
const { token } = await res.json()
this.setState(() => ({ token }))
}
render() {
const {
state: { token }
} = this;
return (
!!token &&
<WebChat.Chat
directLine={{
token,
webSocket: false
}}
style={{
height: '100%',
width: '100%'
}}
user={{
id: 'default-user',
name: 'Some User'
}}
/>
);
}
}
export default App;
Add this line before the title tag in /public/index.html:
<link
rel="stylesheet"
href="https://cdn.botframework.com/botframework-webchat/0.14.2/botchat.css"
/>
package.json -- note I'm using the 0.14.2 version of botframework-webchat, I can't get it to work on the master release (4.1.1 as of right now):
{
"name": "react-test",
"version": "0.1.0",
"private": true,
"dependencies": {
"botframework-webchat": "^0.14.2",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-scripts": "^2.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
And don't forget to set your secret in .env!
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?
If I use a Higher-Order Component (HOC) as a decorator, i.e.,
#withStyles({})
class Bar extends React.Component { ... }
I'd get this error with enzyme:
console.error node_modules/prop-types/checkPropTypes.js:19
Warning: Failed prop type: The prop `classes` is marked as required in `_class`, but its value is `undefined`.
in _class
If I use the function form, i.e.,
const Bar = withStyles({})(class extends React.Component { ... });
there are no errors.
Why?
Note that this warning only happens on a child component; see the code from reproduction steps for what I mean.
Reproduction steps
package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "jest"
},
"author": "",
"dependencies": {
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"babel-jest": "^23.2.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"jest": "^23.3.0"
},
"babel": {
"plugins": [
"transform-class-properties",
"transform-decorators-legacy"
],
"presets": [
"env",
"react"
]
}
}
__tests__/app.test.js:
import Adapter from 'enzyme-adapter-react-16';
import Enzyme from 'enzyme';
import PropTypes from 'prop-types';
import React from 'react';
import { shallow } from 'enzyme';
Enzyme.configure({ adapter: new Adapter() });
const withStyles = styles => Component => class extends React.Component {
render() {
return <Component classes={styles} />
}
}
// This will produce a failed prop type warning:
#withStyles({})
class Bar extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
}
render() {
return <div>test</div>;
}
}
// This will NOT produce a failed prop type warning:
// const Bar = withStyles({})(class extends React.Component {
// static propTypes = {
// classes: PropTypes.object.isRequired,
// }
// render() {
// return <div>test</div>;
// }
// });
class Test extends React.Component {
render() {
return <Bar />;
}
}
it('renders without crashing', () => {
shallow(<Test />);
expect(true).toBe(true);
});
Run npm t
There are two code blocks: one with decoration and the other (currently commented out) with function form. Simply comment out the decorator block and uncomment the function form block to test both cases.
This problem originally arose when using material-ui and I can confirm that both cases render the same UI visually. This prevented me from using the decorator form of withStyles.
Note that there are some more investigations by me here: https://github.com/airbnb/enzyme/issues/1505
The #babel/plugin-proposal-decorators needs come before #babel/plugin-proposal-class-properties, i.e., in the package.json:
"babel": {
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
],