How to use scss modules in Next.js server components - javascript

I am trying to implement server components in my Next.js app. I'm using scss modules for styling.
A typical component in my project looks like this:
//MyComponent.client.jsx
import s from './MyComponent.module.scss';
export const MyComponent = ({ props }) => {
return <div id={ s.wrapper }>{ props.stuff }</div>
};
When I change this to: MyComponent.server.jsx
Styling ceases to work, and I don't get any errors.
How can I maintain this functionality in a server component?

Related

Vue Testing Library: How to mock Vue component

I used React Testing-Library, but not Vue Testing-Library before https://testing-library.com/docs/vue-testing-library/intro/ and I don't want to use mount or shallowMount where I can provide a stub. I want to figure out how to do that in VTL.
We usualy have components that use other components. So when testing our component say ComponentA it may use ComponentB and ComponentC. While there are some components that we want to be rendered (ComponentA and ComponentB) and want to test how they interact with our component, there are also others (ComponentC), which we may not want to test here, because they have their own tests. I.e. we want to "shallow-render" ComponentC when testing ComponentA.
Using react testing library we can do this:
import * as mockedComponentCModule from '....ComponentC';
jest.spyOn(mockedComponentCModule, 'ComponentC').mockImplementation(() => (
<div data-testid="mocked-component-c" />
));
or I like this
jest.mock('path/to/my/ComponentC', () => ({
ComponentC: function ComponentC() {
return <div data-testid="mocked-component-c" />;
}
}));
So in react when we do render(<ComponentA />) the ComponentC will render as a simple div instead of the actual component.
My question is - how can I do this with Vue Testing Library?
I think I figured it out:
jest.spyOn(mockedComponentCModule.default, 'render').mockImplementation((create) =>
create('div', { attrs: { 'data-testid': 'mocked-component-c' } }, 'Test Content')
);
Now sure if there's a better way - I'd be thankful if someone points me in the right direction

How to properly use .scss modules with React components

I have a question regarding how to correctly use .scss modules(and common css modules) when it comes to use the same .scss module in several components at once.
For instance: if a parent & its children need to access the same exact .scss module, which way is the best to access the module?
Assume I have a .scss module which contains all styles and a component AudioPlayer that has a structure like this:
import audioPlayerModule from './SCSS/AudioPlayer.module.scss';
/*Some code*/
return (
<div className={audioPlayerModule.audio_container}>
<LeftControls/>
<CenterControls />
<RightControls/>
</div>)
The main AudioPlayer component uses the module audioPlayerModule. Then let's say I need this module again inside the child component LeftControls:
import audioPlayerModule from './SCSS/AudioPlayer.module.scss';
const LeftControls = () => {
return (
<div className={audioPlayerModule.left_controls_container}></div>
);
}
Thus I have imported the same .scss module "audioPlayerModule" to parent & each of its children. Is there any better way to do it without using "props.children"?
You can pass className props to your child components
<LeftControl className={audioPlayerModule.left_controls_container}/>
and then spread this props in child
const LeftControls = ({props}) => {
return (
<div {...props}></div>
);

Next.JS SSR in component

I want to integrate a module that only support server side rendering. This is project structure.
index.js
view.js
part.js (Class component)
I can use the module in getServerSideProps method in index.js. But I want to use it in part.js since there are some content I need to pass to the module that are available in part.js.
I've tried to pass a function in getServerSideProps as a prop to the component but it doesn't allowed.
Can I run server side rendering code in react class component?
server side rendering just working on pages/ directory , you cant use it in component or ....
if you want to use It on pages/ files and its not working check 2 thing
if you have _app.jsx in your project or not
if you have __app.jsx you should define it right like this
import App from 'next/app';
const MyApp = ({ Component, pageProps }) => {
return (
<Component {...pageProps} />
);
};
MyApp.getInitialProps = async (appContext) => {
const { pageProps } = await App.getInitialProps(appContext);
const { ctx } = appContext;
return { pageProps};
};
export default MyApp;

Convert string React Component to jsx again

I have one question, because read javascript file from NodeJS and send to the client and here I reveive all file as string (which is obvious) and here is my question. Is any solution to convert string component again to the jsx? This is no only html tags so dangerouslySetInnerHTML or similar methods don't work.
My string components looks like typical React component, something like that:
import React from 'react';
import { Row } from 'react-bootstrap;
import Home from './Home'
......
const Index = () => {
const renderHelloWorld = <h1>Hello World</h1>
return (
<div>{renderHelloWorld}</div>
)
}
export default Index;
So this is string I'm struggling with how convert it to jsx (maybe this is impossible) and I should use Server Side Rendering with React methodfs like ReactDOMServer?
You can use just plain old JavaScript to do the trick.
document.querySelector('#elementToBeReplace').innerHTML = renderHelloWorld;
Another Option with react.js is use of dangerouslySetInnerHTML.
<div dangerouslySetInnerHTML={{ __html: renderHelloWorld }} />
Or You can use html-react-parser.
import Parser from 'html-react-parser';
const renderHelloWorld = <h1>Hello World</h1>
<div>{Parser(renderHelloWorld)}</div>
Try this library https://www.npmjs.com/package/react-html-parser.
A utility for converting HTML strings into React components. Avoids the use of dangerouslySetInnerHTML and converts standard HTML elements, attributes and inline styles into their React equivalents.
So, solution for my problem is very popular and simple (in early project stage), to understand problem and fix it we need to go back to the server part of the app. For React applications if we want render jsx file from the server, we have to use server side rendering and above problem will be gone. Maybe I show step by step how enable rendering React component in te server.
Configure backend to enable the ES6 features
Install babel packages
npm install #babel/core #babel/node #babel/preset-env #babel/preset-react --save-dev
There is many ways to configure Babel, I use the nearest package.json for this.
{
......,
/*This have to be in the top level in package.json*/
"babel":{
"presets":[
"#babel/preset-env",
"#babel/preset-react"
]
}
}
More information about babel packages and configurations: https://babeljs.io/docs/en/
Send React component to the client
For this we have to install react and react-dom packages in server side
npm install react react-dom
For example in your server,js or route.js file:
.... //necesarry imported modules
import ReactDOMServer from 'react-dom/server'
import Index from './Index';
router.get('/exampleRoute', (req, res) => {
.... //your route business logic
res.send(ReactDOMServer.renderToString(<Index/>))
})
Render view in the client
...//correct React component
const[state, setState] = useState({Component: ''});
fetch('/exampleRoute')
.then(response => response.json())
.then(data => setState(state => ({...state, Component: data.data));
....
return(
<div dangerouslySetInnerHTML={{ __html: state.Component }}></div>
)
This is only simple example how you can render React component from backend if this is necasarry. This is not guide for complex server side rendering in application which is more complicated thing, but no difficult thing.

React Context API not working from custom NPM component library

I've built a ReactJS component library that I use for multiple projects installed via an NPM package using a sim link. I want to use the context API to pass data from a parent component served from the component library to my base project to be consumed by multiple consumer components also served from the component library. When I try the context is always undefined in my child components.
If I place my consumer component in my provider component within my library it works like a champ but this defeats what I'm trying to achieve. If I export both the provider and the consumer to my base project the consumer doesn't see the provider.
This is from my base project
import { Screen, COD, GenericSocketServer } from 'component-library'
export default class View extends React.PureComponent {
render() {
return (
<Screen className="screen odmb1">
<GenericSocketServer>
<COD />
</GenericSocketServer>
</Screen>
)
}
}
This is my provider code exported from my 'component-library'
import React from 'react';
import MyContext from "./context";
import COD from './../cod';
export default class GenericSocketServer extends React.Component {
render() {
return (
<MyContext.Provider value={{ foo: 'bar' }}>
<COD />
{this.props.children}
</MyContext.Provider>
);
}
}
This is my content code used in 'component-library'
import React from 'react'
const MyContext = React.createContext()
export default MyContext
This is my consumer component exported from 'component-library'
import MyContext from "../GenericSocketServer/context"
class COD extends React.Component {
render() {
return (
<React.Fragment>
<MyContext.Consumer>
{(context) => {
/*
context comes back undefined
I expect { foo: 'bar' }
*/
console.log('context :', context)
return (
<p>This should work</p>
)}}
</MyContext.Consumer>
</React.Fragment>
)
}
}
Context always comes back undefined as if it doesn't see the parent provider. I think I'm ether doing something wrong initializing the context myself or for some reason the two components I'm importing just don't share the same context. Please help!! Not sure if I should give up on this and just use redux.
Maybe you are making multiple instances of the component providing the context. Let's say you have a component Sound, which starts by:
const { Provider, Consumer } = React.createContext();
If you import this library from your main project, the context will be created at the global space. You then use it to render your document tree. But in another component you also imported this library, which had to be resolved during webpack transpilation. It thus has its own copy of the above lines and a context object created in its own space. The problem occurs when you try to use the Consumer, because the Provider was only made by the main project for the first context object, and the second context's provider instance was never instantiated, thus returns undefined.
A solution to the problem is to enforce a single context object, which you can achieve by telling the second component's webpack that the provider-owning library is an external, so when webpack reaches e.g. the "import sound" line, it will not go further and will assume this dependency is resolved at runtime. When runtime comes, it will take it from the same place where the main project is taking it. To do this in webpack, e.g. for above "sound" library, add this to your other component (not main project):
{
...
externals: {
...
'sound': 'sound'
}
...
}
Also in your component package.json:
{
...
peerDependencies: {
"sound": "^1.2.3"
}
}
Apart from Darko's answer, esm and cjs export is also a possible reason for context to fail in a package. If you use the hook in esm and the provider in cjs, you will not get the value for that context.
I recently had a similar issue where I was trying to consume the value of a context inside my library components but using the provider (imported from the package) in the host app.
I managed to solve the issue just by making react and react-dom external and peerDependencies when bundling in rollup.
should your code of consumer be
<React.Fragment>
<MyContext.Consumer>
{value => /* render something based on the context value */}
</MyContext.Consumer>
</React.Fragment>
as stated from the official react doc : https://zh-hant.reactjs.org/docs/context.html
when you define
you can use it like

Categories

Resources