How to write props properly in styled-components? - styled-components

I need to change background based on condition if props.src exist. First part works fine, but place where it has props => props.src not getting rendered properly.
Result is:

You only need props.src rather than the function props => props.src in your url:
background: ${props => props.src === "" ? "#eff1f2" : `url(${props.src}) no-repeat center`};
Styled components won’t execute the nested inner function so it just gets stringified.

Related

Background: url() using .attrs() function

I'm trying to display a different background depending on props with .attrs();
I have the following;
const Heart = styled.div.attrs(props => ({
background: `url(${props => props.filled ? "./media/heart-filled.png" : "./media/heart-empty.png"})`
}))`
//rest of styles here.
`;
However, it doesn't display anything. How exactly does this function work?
I don't know why you're trying to use .attrs here, but it's used to attache some props to a styled component.
https://styled-components.com/docs/api#attrs
To make your code work, you could try:
const Heart = styled.div.attrs(props => ({/* Some aditional props here ! */}))`
background: url(${props => (props.filled ? "./media/heart-filled.png" : "./media/heart-empty.png")}); /* props that you pass into your component can be used here */
/* rest of styles here. */
`;
https://codesandbox.io/s/condescending-brown-lx0lf?file=/src/App.js

How to keep custom attribute in styled component?

I created a simple styled component with a custom property test, but when rendered, the test property just did not appear in the div dom, what happened?
const StyledDiv = styled.div<{
test?: boolean;
}>`
color:red;
`;
//in render function...
<StyledDiv test>it's just test</StyledDiv>
In React boolean value is not passed to the dom element in means that test or test={true} will not be available to the dom. It only supports three types of string, number and object and it will convert those to string so all you need to do is change it too test="" and it will work.
If you are looking to access the prop test in your component you need to do something like this:
const StyledDiv = styled.div`
color: ${({test}) => test ? 'red' : 'blue'};
`;

Why is theme undefined in styled component props?

Here I access theme by passing a callback function to the styled tag. I guess styled calls this callback function with the props as first argument. This works well.
export default function SectionHeading(props: SectionHeadingProps) {
const Heading = styled.h2`
${props => props.theme.green && `
color: green;
`}
`;
return (
<Heading>{propss.children}</Heading>
);
}
In this example I pass an expression that contains the props the component has received. Here, theme is undefined.
export default function SectionHeading(props: SectionHeadingProps) {
const Heading = styled.h2`
${props.theme.green && `
color: green;
`}
`;
return (
<Heading>{props.children}</Heading>
);
}
Why is theme undefined in the second example?
The reason is that these are different "props" and they are evaluated in different times, in the first example, the props are the props passed to the styled component, augmented with theme (provided you used <ThemeProvider .../>. In the second example, it is the props passed to your component.
The injection of the theme is done by styled-component library and only to styled components. Your component doesn't get it (because it is not a styled component).
Btw, your code has redundant nesting and creates a styled component each time it is invoked.
The way to do it is to simply define:
const SectionHeading = styled.div`
${props => (props.theme && props.theme.green && {color: 'green'})};
`;
and then:
export default SectionHeading;
Note that your sample code has a typo in the first part, you wrote {propss.children} (an extra 's').

Create variable from props and reuse in code block with Styled Components?

Ive got a basic styled component working. When the prop isHere is passed then the background is blue.
const Item = styled.ul`
${props => console.log(props.theme.colorGroupSelected)};
${props => (props.isHere ? `background:` + 'blue' : null)};
`;
Instead of blue I need to use the colour colorGroupSelected from my theme but I cant get it to work, I keep getting a syntax error.
const Item = styled.ul`
${props => (props.isHere ? `background:` + props => props.theme.colorGroupSelected : null)};
`;
My code is getting quite hard to read. Is it possible to destructure a variable within a styled block? Something like this:
${const colorGroupSelected = (props => return props.theme.colorGroupSelected)};
${props => (props.isHere ? `background:` + colorGroupSelected : null)};
This works but doesn't destructure the variable:
${props => (props.isHere ? `background:` + props.theme.colorGroupSelected : null)};

Drupal 6 textfield form element with ahah attribute

I have a form with a textfield element which when a user starts typing into I want to pre-populate a different element.
I've been using the #ahah attribute which works fine with the event property set to 'keyup' however I lose focus on the textfield element because the moment the 'keyup' event is fired the whole form is rebuilt due to ahah's behaviour.
I tried setting the event property to 'change' and that works nicely however in order for the 'change' event to fire I need to click away from the textfield - so from UI point of view I cannot expect users to click away from field just to get the results to display.
I'm not sure if it's possible to achieve what I want with AHAH which is fine but I'd like to stick with it if possible.
Happy to provide code if required and sorry if it's not clear, quite difficult to explain.
Thanks
Steve
The whole form shouldn't be re-rendered by the browser. That's precisely the idea AHAH, that you can update just part of a form. Make sure to set the "wrapper" attribute (of the #ahah attribute) to the ID (as in: the HTML attribute) of the DOM element that you want Drupal's JS functionality to update asynchronously.
For example:
<?php
function MYMODULE_some_ahah_enabled_form(&$form_state) {
$initial_markup = '<div>' . t('This content will be replaced') . '</div>';
$form['dynamic_thing'] = array(
'#type' => 'markup',
'#prefix' => '<div id="dynamic-thing">', // Set Drupal's AHAH wrapper to this ID
'#suffix' => '</div>',
'#value' => $initial_markup,
);
$form['field_which_will_trigger_ahah_behavior'] = array(
'#type' => 'textfield',
'#ahah' => array(
'path' => 'MYMODULE/path/to/ahah/callback',
'wrapper' => 'dynamic-thing',
'event' => 'keyup',
),
'#default_value' => 'Change me',
);
return $form;
}
/**
* Your menu callback (which is declared in your hook_menu()) which returns only the HTML that will replace the existing markup in $form['dynamic_thing'].
*/
function MYMODULE_ahah_callback() {
$output = '<div>New content for the dynamic thing</div>';
drupal_json(array('status' => TRUE, 'data' => $output));
exit();
}
Your "field_which_will_trigger_ahah_behavior" DOM element in the browser shouldn't lose focus, or be re-rendered in any way, unless there's something else causing some bug.

Resources