React multiple import one module caching re-use - javascript

I am using Centrifugo websocket server. I need to connect to Centrifugo and store connection instance for future usage from from multiple components.
Will it be the good way to create this kind of export from ./socket.js? Will centrifuge.connect() and centrifuge.setToken('') be executed if I gonna import ./socket.js module muitiple times?
./socket.js
const Centrifuge = require('centrifuge');
const centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket');
centrifuge.setToken('');
centrifuge.connect();
export default {
socket: centrifuge,
};
./App.jsx
import React from 'react';
import { socket } from '../socket'; // first import
import SomeComponent from './components/SomeComponent';
import SomeSecondComponent from './components/SomeSecondComponent';
export default () => (
<>
<SomeComponent />
<SomeSecondComponent />
</>
)
./components/SomeComponent.jsx
import React from 'react';
import { socket } from '../socket'; // second import
export default () => <>...</>;
./components/SomeSecondComponent.jsx
import React from 'react';
import { socket } from '../socket'; // third import
export default () => <>...</>;
What would it be the best way to make instance and reuse it?

If you want to use a single instance only, it's better to import it in one place only. Best to import in the parent component and pass it as props to the children.
So your app.jsx would become:
import React from 'react';
import { socket } from '../socket'; // first import
import SomeComponent from './components/SomeComponent';
import SomeSecondComponent from './components/SomeSecondComponent';
export default () => (
<>
<SomeComponent socket={socket} />
<SomeSecondComponent socket={socket} />
</>
)
Now socket will be available as the props in both the components.
For eg. In ./components/SomeComponent.jsx
import React from 'react';
export default ({socket}) => <>...</>;

Related

I can't see why my context api does not work in reactjs

i have been trying to implement a context api solution since i want to use children states(data) in my app.js without lifting up the states. anyways i have tried to implement it a context api soloution to by doing the following :
i created a folder names context and then created Context.js
the code is as follows:
mport { createContext,useState } from "react";
export const Mycontext = createContext()
const Context = ({children}) =>{
const [post, setPost] = useState([])
return(
<Mycontext.Provider value={[post,setPost]}>
{children}
</Mycontext.Provider>
)
}
export default Context
i wrapped the index.js file with the Provider wrapper as follows:
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import Context from './context/Context';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Context>
<App />
</Context>
);
my main goal for now is to use useState hook data or states so i can use them in higher up comonents , in this case i want my post.js file to change usestate data in context so i can then use that data to post something in App.js using a container component that takes value as a props
i will post the both post.js and container.js and app.js below
import React,{useContext,useState,useEffect,useRef} from 'react'
import '../HomeMainStyling/HomeStyling.css'
import Tweets from './Tweets'
import Context from '../../context/Context'
function Tweet() {
const tw = useRef('')
const {post,setPost} = useContext(Context);
useEffect(() => {
if (post.length) console.log(post);
}, [post]);
function PostNow(event){
event.preventDefault();
setPost((oldpost) => [tw.current.value,...oldpost]);
}
return (
<div className="tweetcontainer">
<textarea ref={tw} className="tweetinfo"></textarea>
<button className="postIt" onClick={PostNow}>tweet</button>
</div>
)
}
export default Tweet
//
the container is the following:
import React from 'react'
import '../HomeMainStyling/HomeStyling.css'
function Tweets({value}) {
return (
<h2>{value}</h2>
)
}
export default Tweets
App.js:
import Tweet from './Center/HomeMain/Tweet';
import Tweets from './Center/HomeMain/Tweets';
import { useContext,useState } from 'react';
import Context from './context/Context';
function App() {
const {post,setPost} = useContext(Context);
return (
<div className="App">
<Tweet/>
<Tweets value={post}/>
</div>
);
}
export default App;
the app should in principle post 1 h1 element for every click in Tweet components
The useContext hook takes the context you created using createContext() as a parameter, but you are passing a custom component to it, so try:
import { Mycontext } from './context/Context';
const [post, setPost] = useContext(Mycontext)
<Mycontext.Provider value={[post,setPost]}>
this is wrong you ahve to write
<Mycontext.Provider value={{post,setPost}}>

Class constructor not getting called

I have a function ChartWrapper and a class called LineChart.
All the code:
index.js ->
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
App.js ->
import React, {useRef, useEffect, useState, Component} from 'react';
import './App.css';
import ChartWrapper from './ChartWrapper'
class App extends Component {
render() {
return (
<div id="app">
<ChartWrapper />
</div>
)
}
}
export default App;
ChartWrapper.js ->
import React, {Component, useEffect} from 'react';
import { useRef } from 'react';
import LineChart from './LineChart'
function ChartWrapper() {
const svgRef = useRef();
console.log("works");
useEffect( () => {
const chart = <LineChart parent = {svgRef} />
console.log(chart);
}, []);
return (
<svg ref={svgRef}>
</svg>
);
}
export default ChartWrapper;
LineChart.js ->
import React, {Component} from 'react'
import {scaleLinear} from 'd3-scale'
import {max} from 'd3-array'
import {select} from 'd3-selection'
class LineChart extends Component {
constructor (props) {
super(props);
this.svg = select(props.parent);
console.log("does this work");
console.log(this.svg);
}
}
export default LineChart;
The ChartWrapper function creates a LineChart object and passes a const as a prop. To check if the code is working, I have print statements. For some reason, the print statements in ChartWrapper work fine. The print statements in LineChart constructor class however do not.
Am I missing something?
What you get in return when you log chart to the console is just an object representing the component, like this:
If you look at the type, it specifies the function/class to call. The class is only instantiated when it's rendered.
And the chart component is not returned, therefore react does not render it.
you need to call the render method for LineChart

Testing prop drilling with Enzyme

I want to write an integration test to assert that a when a parent component drills certain values or properties to a child component, that component receives said values and renders them properly. Below I have two component examples and an example test. Of course, the test is not accurate, but I'm wondering how I can use enzyme to accomplish this? Thanks!
sampleComponent.js:
import React from 'react';
const SampleComponent = () => (
<div test-attr="div">
<SampleChildComponent title="Sample title" />
</div>
);
export default SampleComponent;
sampleChildComponent.js:
import React from 'react';
const SampleChildComponent = ({ title }) => <h3 test-attr="h">{title}</h3>;
export default SampleChildComponent;
sampleComponent.test.js:
import React from 'react';
import { shallow } from 'enzyme';
import SampleComponent from './sampleComponent';
import SampleChildComponent from './sampleChildComponent';
test('renders component without errors', () => {
const wrapper = shallow(<SampleComponent />);
const childWrapper = shallow(<SampleChildComponent />);
expect(childWrapper.text()).toEqual('sample title');
});
To render child components you should use mount instead of shallow:
import { mount } from 'enzyme'
import React from 'react'
import SampleChildComponent from './sampleChildComponent'
import SampleComponent from './sampleComponent'
test('renders component without errors', () => {
const wrapper = mount(<SampleComponent />)
expect(wrapper.find(SampleChildComponent).text()).toEqual('sample title')
})

TypeError: undefined is not an object (evaluating 'store.getState')

I'm following the Let’s Build: Cryptocurrency Native Mobile App With React Native + Redux tutorial.
When I create my store in App.js, the app works fine
import { createStore, applyMiddleware, compose } from 'redux';
import devTools from 'remote-redux-devtools';
import React, { Component } from 'react';
import { Platform, View } from 'react-native';
import { Provider } from 'react-redux';
import promise from 'redux-promise';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import { Header, CryptoContainer } from './src/components';
import rootReducer from './src/reducers';
const middleware = applyMiddleware(thunk, promise, logger);
const Store = createStore(rootReducer, compose(middleware, devTools({
name: Platform.OS,
hostname: 'localhost',
port: 5678
}), ));
export default class App extends Component {
render() {
return (
<Provider store={Store}>
<View>
<Header />
<CryptoContainer />
</View>
</Provider>
);
}
}
but when I move the store logic to a new file ./src/Store.js,
import { Platform } from 'react-native';
import { createStore, applyMiddleware, compose } from 'redux';
import devTools from 'remote-redux-devtools';
import promise from 'redux-promise';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import rootReducer from './reducers';
const middleware = applyMiddleware(thunk, promise, logger);
const Store = createStore(rootReducer,compose(middleware,devTools({
name: Platform.OS,
hostname: 'localhost',
port: 5678
}),
)
);
export default Store;
and use it in App.js like
import React, { Component } from 'react';
import { View } from 'react-native';
import { Provider } from 'react-redux';
import { Header, CryptoContainer } from './src/components';
import { Store } from './src/Store';
export default class App extends Component {
render() {
return (
<Provider store={Store}>
<View>
<Header />
<CryptoContainer />
</View>
</Provider>
);
}
}
I get
TypeError: undefined is not an object (evaluating 'store.getState')
What's causing my build (expo start) to fail when I import Store.js?
It seems the import statement is not right. It should be:
import Store from './src/Store';
if you're importing a single named export
e.g where you've done export const MyComponent = () => {} you'd import it like import { MyComponent } from "./MyComponent"
if you're importing a default export e.g where you've done const MyComponent = () => {} export default MyComponent you'd import it like import MyDefaultComponent from "./MyDefaultExport"
I got this error because I was exporting the wrong component from my main App file.
I was exporting this:
import React from 'react'
import { Provider } from 'react-redux'
import { createAppContainer } from 'react-navigation'
import Navigator from './src/components/Navigator'
import { store } from './src/store'
const App = createAppContainer(Navigator);
const Wrapped = props => (
<Provider store={store}>
<App />
</Provider>
)
export default Provider; // wrong!
That last line should be:
export default Wrapped; // right!
The answer from Itunu Adekoya shows that you can decide how you want to export / import, and in this case about personal preference, as there isn't a perf difference.
In the case where you have a lot of exports from a file, and perhaps some are unrelated or won't all be used together, it is better to export them individual as consts and then in other file only import what you need via import { } format, this will be sure to only include relevant imprts
in my case its casing & named import issue. imported as
import store from './Redux/Store'
it should be
import {Store} from './Redux/Store'

React/Redux Changing Webpage language

I'm making a website that have a functionality to change languages from the homescreen, I'm using Redux to handle the state.
I keep getting TypeError: Cannot read property 'connect' of undefined, and It seems to be from Home.js, I dont know why it happens!!, Please Help !!!
import React, { Component } from 'react';
import ReactRedux from 'react-redux';
import './Home.css';
import Navbar from '../../Reusable/Navbar/Navbar.js';
import Footer from '../../Reusable/Footer/Footer.js';
import Action from '../../Reusable/Action/Action.js';
import ProjectsCarousel from '../../Reusable/ProjectsCarousel/ProjectsCarousel.js';
import Getintouch from '../../Reusable/Getintouch/Getintouch.js';
import Header from './Header/Header.js';
import Info from './Info/Info.js';
import Whyus from './Whyus/Whyus.js';
import Testimonial from './Testimonial/Testimonial.js';
let actions = require('../../../actions');
class Home extends Component {
render() {
const content = this.props.content;
const switchLanguage = this.props.switchLanguage;
if (content){
return (
<div className="home">
<Action />
<Navbar data={content.page.menu} switchLanguage={switchLanguage}/>
<Header />
<Info data={content.page.home}/>
<ProjectsCarousel />
<Whyus />
<Testimonial />
<Getintouch />
<Footer />
</div>
)
} else {
return;
}
}
}
module.exports = ReactRedux.connect(
(state) => ({content: state.content}),
(dispatch) => ({switchLanguage: (lang) => dispatch(actions.switchLanguage(lang))})
)(Home);
export default Home;
That's because react-redux has only named exports.
change your import to:
import * as ReactRedux from 'react-redux';
which will import every named property to ReactRedux Object. or import it like:
import { connect } from 'react-redux';
export default connect(
(state) => ({content: state.content}),
(dispatch) => ({switchLanguage: (lang) => dispatch(actions.switchLanguage(lang))})
)(Home);

Categories