SplashScreen in react native - timer

I need to make an image as a background for the whole first screen as a SplashScreen and after some fixed time it shows the other component.
I created two components Home and SplashScreen and here is the code i'm using:
componentDidMount() {
SplashScreen.hide();
}
render() {
return(
<View>
<SplashScreen/>
<Home/>
</View>
)
}
Please any help or idea

You need to implement this in Javascript land.
Top most component would hold a flag indicating to render splash screen.
Update this flag after specified amount of time and render desired content.
Dummy implementation may look like this...
class App extends Component {
state = {
ready: false,
}
componentDidMount () {
setTimeout(() => {
this.setState({ ready: true })
}, 5000)
}
render() {
if (this.state.ready === false) {
return <Splash />
}
return this.props.children;
}
}
// Usage example:
<App>
<RouterOrSomething />
</App>

Related

How to reload the current component in react?

I've have an component "A" with a button. When the user press the button I'm showing a modal(react-responsive-modal) with bunch of filed and an update button. When the user presses the update button on the modal I want to reload the component "A" with the updated data.
I tried redirecting using this.props.history.push('dashboard/componentA') but it didn't work. Then I tried redirecting to the dashboard and again redirecting to the component like this
this.props.history.push('/dashboard');
this.props.history.push('/dashboard/componentA');
It worked but I'm not seeing any loader that I've used on 'componentWillMount' and the component just freezes up. I couldn't scroll up or down.
Try not to use the browser history as a way to update react (as much as you can). React is designed to re-render components when the props or state for that component change. As an example, this should trigger an update in ComponentA without needing to update the browser's history:
class ComponentA extends Component {
handleModalClick = (event) => {
this.setState({
componentData: event.data,
});
}
render() {
return (
<ReactModal onClick={this.handleClick} />
)
}
}
EDIT: Updated to show a data fetching parent component:
class DataFetcher extends Component {
saveAndFetchData = (saveData) => {
FetchDataPromise(saveData).then((updatedData) => {
this.setState({ data: updatedData });
}
}
render() {
const { data } = this.state;
return (
<div>
<ComponentA data={data} />
<ReactModalComponent handleClick={saveAndFetchData} />
</div>
);
}
}
class ComponentA extends Component {
render() {
const { data } = this.props;
return (
<div>
...render data...
</div>
)
}
}

how to stop update in reactjs

I stuck in bit weird situation, I am using ReactJS. I have header container, title bar, title container. Header container has navigation bar. On click of that it effects title bar. I am using react router for that navigation. I am using componentDidMount lifecycle method for that.
Problem with that it triggers only once when title container loads. So I used componentDidUpdate. But in that problem occured when I added title bar component to title container. So now my componentDidUpdate runing in infinite loop. I tried to use shouldComponentUpdate(nextProps, nextState) but I don't know what condition put to return it false.
export class TitleContainer extends React.Component {
componentDidMount() {
this.props.dispatch(fetchDetail(this.props.match.params.program_id))
}
componentDidUpdate(prevProps, prevState) {
this.props.dispatch(fetchDetail(this.props.match.params.id))
}
shouldComponentUpdate(nextProps, nextState){
console.log("current props",this.props)
console.log("next props",nextProps)
// if(this.props.name == nextProps.name)
// return false;
return true;
}
render() {
console.log("data in contaner", this.props)
return (
<div>
<Title name = { this.props.name }
/>
</div>
)
}
}
const mapStateToProps = (state) => {
console.log("update state", state)
return {
programProfileData: state.DetailReducer.Details,
name: state.DetailReducer.name
}
}
export default connect(mapStateToProps)(TitleContainer)
If I understand your problem you would like to fetch other data if you change the params?
If so I would just remount the whole component.
class TitleContainer extends React.Component {
componentDidMount() {
this.props.dispatch(fetchDetail(this.props.match.params.program_id))
}
render() {
console.log("data in contaner", this.props)
return (
<div>
<Title name = { this.props.name }
/>
</div>
)
}
}
const mapStateToProps = (state) => {
console.log("update state", state)
return {
programProfileData: state.DetailReducer.Details,
name: state.DetailReducer.name
}
}
export default connect(mapStateToProps)(TitleContainer)
I think you don't need to use componentUpdate. You navigate to your that address, react router will creates that component, and you can extract the match props.
In your header you can have other Links from the react router dom lib which will replace your existing component. If you click on a link, react router pushes that to the browser history and creates a new component and therefore the params are updated.

Child route is blocking the parent route`s render

I have a react app which is using react-router. I`m using plain routes, but this is how components represent my routing
<Routes>
<Route component={CoreLayout}>
<Route component={AppLayout}
onEnter={fetchData}>
<Route path='dashboard'
onEnter={fetchStatistics}
component={Dashboard}>
</Route>
</Route>
</Routes>
The situation now
First, the app layout is going to block every render while it is fetching the necessary data from the server (like the User data). Then if we have the data, we can step on the child routes, like in this case the Dashboard route, where we are loading the content of the pages.
The goal
The problem is whit this strategy, we are going to show a blank white page until the onEnter on the main route is resolved.
To avoid this, I would like to load the AppLayout component, but without starting the onEnter function on the child route. To do this, I can show a waiting spinner where the child component would load, and when the data is loaded I can start loading the child`s data.
tl;dr
The question is, how can I make the parent layout to render, while the child route`s onEnter is not loaded.
Instead of using onEnter, you can have your <Dashboard> initiate its data fetching in its component(Will|Did)Mount method. Have it maintain a state.loaded boolean which displays a spinner when state.loaded = false.
class Dashboard extends React.Component {
constructor(props) {
super(props)
this.state = {
loaded: false
}
}
componentWillMount() {
// mock data fetch call that uses a promise
fetchStatistics()
.then(resp => resp.json())
.then(data => {
this.setState({
loaded: true,
data
})
})
}
render() {
// if data hasn't been loaded, render a spinner
if (!this.state.loaded) {
return <Spinner />
}
// data has been loaded, render the dashboard
return (
<div>...</div>
)
}
}
Edit:
It doesn't handle data loading errors, but here is an example of a general purpose data loading HOC that should work (haven't tested it):
/*
* #Component is the component to render
* #fetchData is a function which fetches the data. It takes
* a callback function to trigger once data fetching has
* completed.
*/
const withData = (Component, fetchData) => {
return class WithData extends React.Component {
constructor(props) {
super(props)
this.state = {
loaded: false
}
}
componentWillMount() {
this.props.fetchData(() => {
this.setState({ loaded: true })
})
}
render() {
return this.state.loaded ? (
<Component {...this.props} />
) : (
<Spinner />
)
}
}
}
Usage
function fetchStatistics(callback) {
fetch('/api/dashboard')
.then(resp => resp.json())
.then(data => {
dispatch(dashboardData(data))
callback()
})
})
<Route
path='dashboard'
component={withData(Dashboard, fetchStatistics} />

In my React-Native, app, I am looking to see if the use is logged in before I initialize the beginning scene

Here is my most recent attempt of trying to render the scene. I was originally attempting to do it in the renderScene function, but tried another method. The problem here is that _loadInitialState() doesn't finish running before the initial scene runs. I'm sure there is a better way to do this anyways. Here my component:
get initialScene;
class MainNav extends Component {
componentDidMount() {
this._loadInitialState().done();
}
async _loadInitialState() {
try {
let token = await AsyncStorage.getItem("tokenKey");
if (token !== null) {
initialScene = 'home';
} else {
initialScene = 'login';
console.log(token);
}
} catch (error) {
console.log(error.message);
}
}
renderScene(route, nav) {
switch(route.name) {
case 'login':
return (
<Login />
);
case 'home':
return (
<MainCamera />
)
}
}
render() {
return(
<Navigator
_loadInitialState={this._loadInitialState.bind(this)}
initialRoute={{name: initialScene}}
renderScene={this.renderScene.bind(this)}
/>
);
}
}
It is because your running your code in componentDidMount so your app waits till the UI is rendered. Why don't you just do it in your constructor like:
constructor(props) {
super(props)
this._loadInitialState().done();
}
Or you can just simply do it in another class as a dispatcher that checks whether the user is logged in or not and then it does the navigation and the dispatcher doesn't have any interface or it just could be a splash page depending on your use case.

Flux / Flummox: Component stops listening the Store after first router transition

I've just started using flummox and I'm a little bit flummoxed :)
Here is my use case.
App Layout
<section id="layout">
<Header {...this.props} />
<RouteHandler {...this.props} />
<Footer />
<Alert {...this.props} />
</section>
In my App I have Alert Component. When something happens I trigger an AlertAction from some component, it dispatches alert payload to AlertStore, which gets updated, and AlertComponent shows alert ( + hides it after some time).
For example I have a PostEdit Component. After form submit, I send request to API from PostActions and receive response, which is dispatched to PostStore. Store gets updated and PostEdit Component gets notified. In PostEdit's componentWillReceiveProps I check props, received from the store, and trigger AlertAction to show the alert.
2 problems:
I have to use setTimeout to trigger AlertAction from the Post Component to make alert things happen (code below).
And the main problem is that Alert Component stops listening AlertStore after the first react-router transition.
Here is console.log, illustrating the problem:
One more strange thing is that changed-store-notification in console.log printed before dispatch-payload-from-action-notification (which causes this store change).
Here are code snippets:
AlertHandler.jsx
export default class AlertHandler extends React.Component {
// constructor()
render() {
return (
<FluxComponent connectToStores={'alerts'}>
<Alert {...this.props} />
</FluxComponent>
);
}
}
Alert.jsx
export default class Alert extends React.Component {
// constructor()
// _handleShow()
// _handleHide()
componentDidMount() {
this.props.flux.getStore('alerts').addListener('change', function() {
console.log('Changed!', this.state);
});
}
componentWillUnmount() {
console.log('Not gonna happen');
}
// render()
}
PostEdit.jsx
export default class PostEdit extends React.Component {
// constructor()
componentWillReceiveProps(newProps) {
this.setState({
isLoading: false
}, () => {
if (newProps.errors) {
// without `setTimeout` nothing happens
setTimeout(() => {
newProps.flux
.getActions('alerts')
.showErrorAlert(newProps.errors);
}, 1);
} else {
setTimeout(() => {
newProps.flux
.getActions('alerts')
.showSuccessAlert();
}, 1);
}
});
}
_submitPost(e) {
// doing stuff...
// triggering updatePost action
this.props.flux
.getActions('posts')
.updatePost(post);
}
// render()
}
Not sure are these bugs or I missed smth in flux/flummox patterns and do things wrong. Thanks for feedback!

Resources