redux store.dispatch not working within nesting component - redux

I did experimental work to deeply dilute its complexity, but it did not work. While I click the + button, no reaction. To quick start and imagine what I said for helpers, I create it in the link:
http://plnkr.co/edit/FjnUOZvyN0ft0jxq
const reducer=(state=0,action)=>{
switch(action.type){
case'INCREMENT':return state+1;
case'DECREMENT':return state-1;
default:return state;
}
}
const {createStore}=Redux;
const store = createStore(reducer);
const Counter=()=>{
return(
<div>
<p id='number'>{store.getState()}</p><br/>
<button id='increment' onClick={store.dispatch({type:'INCREMENT'})}>+</button>
<button id='decrement'>-</button>
</div>
)
}
const render=ReactDOM.render(
<React.StrictMode>
<Counter />
</React.StrictMode>,
document.getElementById('root')
);
// Add your code here
store.subscribe(render);
render()
;

That is not how you couple react and redux (you would need to use the react-redux library, the Provider component and the useDispatch and useSelector hook. Never reference store in one of your components directly!).
Or make react rerender at all.
Also, this is a very old style of redux that will make you write a multitude more code than you need in the end.
I suggest you follow the official redux tutorials available at https://redux.js.org/tutorials/index

Related

How i can Remove Data from redux automatic using setTimeOut

Hiii i have one array like more than one object and when store data from redux i need to remove automatic from array after 5 second.
welcome to the community! For your problem maybe use a useEffect hook in the app component, eg:
import foo from "foo.js";
import blahblahblah from "xxx.js";
import React from "react";
import {useDispatch} from "react-redux";
// ..;
function App(){
const dispatch = useDispatch();
React.useEffect(()=>{
while(true){
setTimeout(()=>{
dispatch.runSomthing(myAmazingData);
},5000);
}
}, []);
return(
<div>
<p>Welcome to my amazing website😀</p>
</div>)
}
export default App;
Next time, show some code! And explain your intentions and what you want to do.
Thanks!

React-tooltip and Next.js SSR issue

I use the react-tooltip library in my Next.js app.
I noticed that every time I refresh a website while visiting a page that uses the tooltip I get an error:
react-dom.development.js:88 Warning: Prop `dangerouslySetInnerHTML` did not match.
CSS classes are different on the client and on the server
The weird part is I do not get that error while navigating from a random page to a page that uses the react-tooltip.
The tooltip related code:
<StyledPopularityTooltipIcon src="/icons/tooltip.svg" alt="question mark" data-tip="hello world" />
<ReactTooltip
effect="solid"
className="tooltip"
backgroundColor="#F0F0F0"
arrowColor="#F0F0F0"
clickable={true}
/>
I had the same issue, I had to use state to detect when component has been mounted, and show the tooltip only after that.
P.S. You don't see the error when navigating, because the page is not rendered on server when you navigate, it's all front-end :)
In case you are using any server-side rendering (like Next.js) - you will need to make sure your component is mounted first before showing the react-tooltip.
I fixed this by using the following:
import React, { useEffect, useState } from 'react';
const [isMounted,setIsMounted] = useState(false); // Need this for the react-tooltip
useEffect(() => {
setIsMounted(true);
},[]);
return (<div>
{isMounted && <ReactTooltip id={"mytip"} effect={"solid"} />}
<span data-tip={"Tip Here"} data-for={"mytip"}>Hover me</span>
</div>)
You should wrap your JSX in the following component:
import React, { useEffect, useState } from 'react';
const NoSsr = ({ children }): JSX.Element => {
const [isMounted, setMount] = useState(false);
useEffect(() => {
setMount(true);
}, []);
return <>{isMounted ? children : null}</>;
};
export default NoSsr;
Like this:
<NoSsr>
<YourJSX />
</NoSsr>
If you are working with NEXTJS this might be a good approach, you can check the documentation here as well, also if you are working with data-event, globalEventOff or any other prop and is not hiding or not working in your localhost, this only occurs in Development Strict Mode. ReactTooltip works fine in Production code with React 18. So you can set reactStrictMode : false, in your next.config.js to test it locally and then set it back to true, hope this helps :) info reference here
import dynamic from 'next/dynamic'
const ReactTooltip = dynamic(() => import('react-tooltip'), { ssr : false });
function Home() {
return (
<div>
<Button
data-tip
data-event="click focus"
data-for="toolTip"
onClick={():void => ()}
/>
<ReactTooltip id="toolTip" globalEventOff="click"/>
</div>
)
}
export default Home

Dynamically load .css based on condition in reactJS application

I have a reactJS application that I want to make available to multiple clients. Each clients has unique color schemes. I need to be able to import the .css file that corresponds to the specific client.
For example, if client 1 logs into the application, I want to import client1.css. if client 2 logs into the application, I want to import client2.css. I will know the client number once I have validated the login information.
The application contains multiple .js files. Every .js file contains the following at the top of the file
import React from 'react';
import { Redirect } from 'react-router-dom';
import {mqRequest} from '../functions/commonFunctions.js';
import '../styles/app.css';
Is there a way to import .css files dynamically for this scenario as opposed to specifying the .css file in the above import statement?
Thank you
Easy - i've delt with similar before.
componentWillMount() {
if(this.props.css1 === true) {
require('style1.css');
} else {
require('style2.css');
}
}
Consider using a cssInJs solution. Popular libraries are: emotion and styled-components but there are others as well.
I generally recommend a cssInJs solution, but for what you are trying to do it is especially useful.
In Emotion for example they have a tool specifically build for this purpose - the contextTheme.
What cssInJs basically means is that instead of using different static css files, use all the power of Javascript, to generate the needed css rules from your javascript code.
A bit late to the party, I want to expand on #Harmenx answer.
require works in development environments only, once it goes to production you're likely to get errors or not see the css file at all. Here are some options if you, or others, encounter this:
Option 1: Using css modules, assign a variable of styles with the response from the import based on the condition.
let styles;
if(this.props.css1 === true) {
//require('style1.css');
import("./style1.module.css").then((res) => { styles = res;});
} else {
//require('style2.css');
import("./style2.module.css").then((res) => { styles = res;});
}
...
<div className={styles.divClass}>...</div>
...
Option 2: using Suspend and lazy load from react
// STEP 1: create components for each stylesheet
// styles1.js
import React from "react";
import "./styles1.css";
export const Style1Variables = (React.FC = () => <></>);
export default Style1Variables ;
// styles2.js
import React from "react";
import "./styles2.css";
export const Style2Variables = (React.FC = () => <></>);
export default Style2Variables ;
// STEP 2: setup your conditional rendering component
import React, {lazy, Suspense} from "react";
const Styles1= lazy(() => import("./styles1"));
const Styles2= lazy(() => import("./styles2"));
export const ThemeSelector = ({ children }) => {
return (
<>
<Suspense fallback={null} />}>
{isClient1() ? <Styles1 /> : <Styles2/>}
</Suspense>
{children}
</>
);
};
// STEP 3: Wrap your app
ReactDOM.render(
<ThemeSelector>
<App />
</ThemeSelector>,
document.getElementById('root')
);
Option 3: Use React Helm which will include a link to the stylesheet in the header based on a conditional
class App extends Component {
render() {
<>
<Helmet>
<link
type="text/css"
rel="stylesheet"
href={isClient1() ? "./styles1.css" : "./styles2.css"}
/>
</Helmet>
...
</>
}
}
Personally, I like option 2 because you can set a variable whichClientIsThis() then modify the code to:
import React, {lazy, Suspense} from "react";
let clientID = whichClientIsThis();
const Styles= lazy(() => import("./`${clientID}`.css")); // change your variable filenames to match the client id.
export const ThemeSelector = ({ children }) => {
return (
<>
<Suspense fallback={null} />}>
<Styles />
</Suspense>
{children}
</>
);
};
ReactDOM.render(
<ThemeSelector>
<App />
</ThemeSelector>,
document.getElementById('root')
);
This way you don't need any conditionals. I'd still recommend lazy loading and suspending so the app has time to get the id and make the "decision" on which stylesheet to bring in.

useSelector with React.memo vs connect

referring from the link.
https://react-redux.js.org/next/api/hooks#performance
what i understand the benefit of useSelector hook, is to avoid wrapper hell. Wrapper hell is happening due to the usage of connect HOC. If we have to use React.memo HOC with useSelector due to perfomance reason, would it be better approach to simply use connect HOC instead? Because in any case we would have to be in hell of wrappers. If the hell is not by connect then would be by React.memo.
Any one please explain the benefit of React.memo over connect.
Well, first, interesting enough although React.memo is a HOC it does not create the same nesting as connect does. I have created a test code:
import React from "react";
import ReactDOM from "react-dom";
import {connect, Provider} from 'react-redux'
import { createStore } from 'redux'
import "./styles.css";
const MemoComponent = React.memo(function MyMemo() {
return <div>Memo</div>;
});
const ConnectedComponent = connect(null,null)(function MyConnected() {
return <div>ReduxConnectComponent</div>;
})
const store = createStore(()=>{},{})
function App() {
return (
<Provider store={store}>
<MemoComponent />
<ConnectedComponent/>
</Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
And here is the structure rendered:
We can see that a content for connect is rendered deeper.
Second, the docs say:
by default useSelector() will do a reference equality comparison of the selected value when running the selector function after an action is dispatched, and will only cause the component to re-render if the selected value changed. However, unlike connect(), useSelector() does not prevent the component from re-rendering due to its parent re-rendering, even if the component's props did not change.
that means the component which useSelector will not be re-rendered when unrelated parts of the store change. And this is the most important part of the optimization. Whether optimizing with React.memo or not is now completely depends on your decision and in most cases, it simply is not needed. We use React.memo only in cases when the component is very expensive to render.
To summarize, connect wrapper was required to connect to the store. With useSelector we do not have to wrap anymore. We still need to wrap with React.memo in rare cases when we need to optimize some heavy components. The work of React.memo was also done by connect but in most cases, it was premature optimization.
I have been trying to get an answer for quite some time but the answers I got weren't clear. Although the theory in the Redux documentation isn't complicated: useSelector uses strict equality === and connect uses shallow equality to determine. So in both cases, if you are "pulling" a primitive value from your Redux state (number, string, boolean) you will be having the same outcome. If values haven't changed none of the components will rerender. If you are "pulling" non-primitives (arrays or objects) and the values haven't changed for both cases (useSelector, connect), then the component that uses useSelector will still rerender as of course [] === [] will always be false, as they are referencing different arrays, where as the connected component will NOT rerender. Now in order to make useSelector behave similarly and not rerender, you can do this:
const object = useSelector(state => state.object, shallowEqual) You can import shallowEqual from react-redux. Or alternatively use a memoized version of that piece of state by using the reselect library:
const makeGetObject = () => createSelector(state => state.object, object => object)
and add it to your selector such as: const object = useSelector(state => state.object, makeGetObject); I have created this codesandbox when I was trying to get at the bottom of it (check the comments at the WithUseSelector component): useSelector vs connect()
I just customized useSelector hook to avoid that and it works nice
import { useSelector, useDispatch } from 'react-redux'
import { _lodash } from '../../../lodash'
export const useCloneSelector = (selector = (obj) => obj) => {
const selectWithClonedState = (state = {}, ...others) => selector(_lodash.cloneDeep(state), ...others)
return useSelector(selectWithClonedState, _lodash.isEqual)
}
export { useDispatch, useSelector }

Contextual styling of ReactJS styled-components

I'm running into problems with Styled Components, and I'm not sure if it's a technical limitation, or if my mental model of how to use them is wrong.
In this example (I just wrote it quickly in Codepen, so disregard spelling mistakes) I have a component that is a username in a span. I want to be able to use that component anywhere, so it's styling is pretty minimal:
// From User.js
import React from 'react';
import styled from 'styled-components';
const Username = styled.span`
color: black;
`
const User = () => (
<UserName>bla</Username>
);
export default User;
I want to be able to use this span in a different component, but in that case I want it's styling to be overridden in this context:
// From Userblock.js
import React from 'react';
import styled from 'styled-components';
import User from './user';
const UserWrapper = styled.div`
// Some styles
`
const User = styled(User)`
color: red; // Different color when displayed in a UserBlock
`
const UserBlock = () => (
<UserWrapper>
<User />
</UserWrapper>
);
export default UserBlock;
From what I know, that's the way to set styling on a third party component (and that works elsewhere in my application), and it should work as far as I can tell, but I get nothing.
Also, going back to the mental model question - is this the way you're supposed to do it when you're using styled-components?
Thanks for any help!
When you wrap a normal React component with styled(X) you need to make sure to attach the class that styled-components passes in.
This means for your example, this will solve the issue:
const User = (props) => (
<UserName className={props.className}>bla</Username>
);
When you override the styles of an existing component styled-components goes ahead, generates a class, injects it and passes it to the component. That means if you don't attach the class to anything you'll never see the styles though! (see the documentation for more information)

Resources