Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions that are interpolated in css calls will be stringified. #1085

Closed
FezVrasta opened this issue Dec 7, 2018 · 11 comments
Closed

Functions that are interpolated in css calls will be stringified. #1085

FezVrasta opened this issue Dec 7, 2018 · 11 comments

Comments

@FezVrasta
Copy link
Member

FezVrasta commented Dec 7, 2018

  • emotion version: 10.0.2
  • react version: 16.3

Relevant code.

// @flow
import { type SerializedStyles } from '@emotion/utils';
import themeData from './theme';

// Use this function in your components to provide a fallback theme in case
// no ThemeProvider is available
const withFallback = (fn: Object => SerializedStyles) => ({
  theme,
  ...props
}: {
  theme: Object,
}) => {
  const t = Object.keys(theme).length ? theme : themeData.light;
  return fn({ theme: t, ...props });
};

export default withFallback;

What you did:

I created this function to be used in my UI library to make sure a theme is always defined
even if no ThemeProvider is available.

Usage:

css`
  color: ${withFallback(props => props.theme.primary)};
`

What happened:

When I run it, in some contexts, I get this error:

console.error node_modules/@emotion/serialize/dist/serialize.cjs.dev.js:135
      Functions that are interpolated in css calls will be stringified.
      If you want to have a css call based on props, create a function that returns a css call like this
      let dynamicStyle = (props) => css`color: ${props.color}`
      It can be called directly with props or interpolated in a styled call like this
      let SomeComponent = styled('div')`${dynamicStyle}`

and the resulting CSS, in fact, is the stringified function.

Reproduction:

https://github.com/FezVrasta/emotion-interpolation-repro

Just run the tests to see the error

Problem description:

My withFallback function seems to work fine if used as:

css`
  color: ${withFallback(props => props.theme.primary)};
`

but throws error if used as:

const textStyles = () => css`
  color: ${withFallback(props => props.theme.primary)};
`;

css`
  ${textStyles()}
`;

(I also tried:

const textStyles = () => () => css`
  color: ${withFallback(props => props.theme.primary)};
`;

with the same result)

Suggested solution:

Not sure

@FezVrasta
Copy link
Member Author

I found out the minimum reproducible example:

// @flow
import styled from '@emotion/styled';
import { css } from '@emotion/core';

const color = css`
  color: ${props => props.color};
`;

const App = styled.div`
  ${color};
`;

export default App;
console.error node_modules/@emotion/serialize/dist/serialize.cjs.dev.js:135
      Functions that are interpolated in css calls will be stringified.
      If you want to have a css call based on props, create a function that returns a css call like this
      let dynamicStyle = (props) => css`color: ${props.color}`
      It can be called directly with props or interpolated in a styled call like this
      let SomeComponent = styled('div')`${dynamicStyle}`

@FezVrasta
Copy link
Member Author

FezVrasta commented Dec 7, 2018

Just for completeness, my use case is the following:

import { css } from '@emotion/core';

const styles = {
  a: props => css`
    color: ${props.a};
  `,
  b: props => css`
    color: ${props.b};
  `,
};

export const textStyles = (...ss) => props => ss.map(s => styles[s]);

test

it('it does not break', () => {
  expect(
    css`
      ${textStyles('a', 'b')};
    `.styles
  ).toMatchSnapshot();
});

edit
I also noticed some inconsistency between css and styled, the function above renders the expected CSS when used inside styled.div but renders the stringified function if used inside css. But in both cases I get the message about functions getting stringified.

@Andarist
Copy link
Member

Andarist commented Dec 7, 2018 via email

@FezVrasta
Copy link
Member Author

I see, but I still get the same error message (even tho, it works) if I use styled with some default props. Test out my latest example with this test:


it('works with "withFallback" powered styles', () => {
  const T = styled.div`
    ${textStyles('secondary', 'disabled', 'link', 'highlighted')}
  `;
  expect(mount(<T />)).toMatchSnapshot();
});
console.error node_modules/@emotion/serialize/dist/serialize.cjs.dev.js:135
      Functions that are interpolated in css calls will be stringified.
      If you want to have a css call based on props, create a function that returns a css call like this
      let dynamicStyle = (props) => css`color: ${props.color}`
      It can be called directly with props or interpolated in a styled call like this
      let SomeComponent = styled('div')`${dynamicStyle}`

@FezVrasta
Copy link
Member Author

Ok nevermind, it was something wrong with my dirty setup, it actually works inside styled. Thanks for the support!

@lynndylanhurley
Copy link

@FezVrasta I'm having the same issue. What was the issue with your setup?

@WNemencha
Copy link

This issue still ranks high on search engines, so here's a solution.

// @flow
import styled from '@emotion/styled';
import { css } from '@emotion/core';

- const color = css`
+ const color = props => css`
-  color: ${props => props.color};
+  color: ${props.color};
`;

const App = styled.div`
  ${color};
`;

export default App;

@littlehome-eugene
Copy link

what about conditionals such as

 const disableStyle = props => css`
 color: ${props => (props.disabled ? props.theme.colors.disabled : null)};

@2Steaks
Copy link

2Steaks commented Sep 21, 2020

This is what I do or plan to do: https://codesandbox.io/s/determined-morse-oehqv

export const get = (props) => (key) => props[key];

export const styleWithHelpers = (fn) => (props) => {
  return fn({ get: get(props) }, props);
};

---------

import styled from '@emotion/styled';
import { css } from '@emotion/core';
import { styleWithHelpers } from 'some-module';

const color = styleWithHelpers(({ get }) => css`
  color: ${get('color')};
`);

const App = styled.div`
  ${color};
`;

export default App;

@alchemist-bounty
Copy link

alchemist-bounty commented Jun 23, 2022

What is the solution for this issue?

const track = css`
   background: ${({ theme }) => rgba(theme.colors.gray['000'], 0.25)};
 `

How can I convert this code to remove the error?
@FezVrasta can you give me the solution for this please?

@WNemencha
Copy link

@alchemist-bounty try something like that;

const track = ({ theme }) => css`
  background-color: ${rgba(theme.colors.gray['000'], 0.25)};
`;

const StyledTrack = styled.div`
  ${track};
`;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants