1

I have some state that changes after button click. The state changes the size of a sidebar.

Here is my CSS made with styled-components and conditional rendering:

const SidebarStyled = styled.div`
    width: ${this.state.sidebarOpen ? '200px' : '70px'};
    position: fixed;
    left: 0px;
    top: 0px;
    height: 100vh;
    background-color: #0c1635;
    display: flex;
    flex-direction: column;
`;

Any idea how I can apply a transition 0.2s on the conditional rendering?

I have tried to add transition: all 0.2s ease-in-out; and it didn't work.

romellem
  • 5,792
  • 1
  • 32
  • 64
  • You don't want to access `this.state` within a styled component declaration, you want to pass in a prop. I'd suggest reading the documentation, starting here - [Styled Components Basic: Adapting based on props](https://styled-components.com/docs/basics#adapting-based-on-props). – romellem Mar 01 '22 at 14:49
  • This project is from a client, and he does not want to change his component.... –  Mar 01 '22 at 14:56
  • 1
    Then they are using styled-components incorrectly, and you won't be able to animate this. By defining the component within a component method (I'm guessing its `render()`), you are recreating that DOM element every time, so there is no way to have CSS transitions apply because the element is constantly getting recreated. – romellem Mar 01 '22 at 14:57

3 Answers3

2

As I mentioned in my comment, you need to pass in a prop and interpolate it out to change your CSS. Otherwise your component will re-render, and the CSS transition won't be applied.

const { React, ReactDOM, styled } = window;

class WontWork extends React.Component {
    constructor(props) {
        super(props);
        this.state = { sidebarOpen: false };
    }

    render() {
        const Sidebar = styled.div`
            width: ${this.state.sidebarOpen ? "200px" : "70px"};
            height: 20px;
            background: red;
            transition: width 1s;
        `;

        return (
            <main>
                <p>This won't work:</p>
                <Sidebar />
                <button
                    onClick={() => this.setState({ sidebarOpen: !this.state.sidebarOpen })}
                >
                    Expand
                </button>
            </main>
        );
    }
}

const WorkingSidebar = styled.div`
    width: ${(props) => (props.open ? "200px" : "70px")};
    height: 20px;
    background: green;
    transition: width 1s;
`;

class WillWork extends React.Component {
    constructor(props) {
        super(props);
        this.state = { sidebarOpen: false };
    }

    render() {
        return (
            <main>
                <p>You need to pass in a <b>prop</b> to a predefined styled-component:</p>
                <WorkingSidebar open={this.state.sidebarOpen} />
                <button
                    onClick={() => this.setState({ sidebarOpen: !this.state.sidebarOpen })}
                >
                    Expand
                </button>
            </main>
        );
    }
}

ReactDOM.render(
    <div>
        <WontWork />
        <hr />
        <WillWork />
    </div>,
    document.getElementById("app")
);
<script crossorigin src="https://unpkg.com/react@16.14.0/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.14.0/umd/react-dom.development.js"></script>

<script crossorigin src="https://unpkg.com/react-is@16.13.1/umd/react-is.production.min.js"></script>
<script crossorigin src="https://unpkg.com/styled-components@5.3.3/dist/styled-components.min.js"></script>

<div id="app"></div>
romellem
  • 5,792
  • 1
  • 32
  • 64
0

Try this:

You can passe sidebarOpen as props:

<SidebarStyle sidebarOpen = {this.state.sidebarOpen}> 

Then:

const sidebarStyle = styled.div`
     width: 70px;
     transition: transform .2s ease-in-out;
     transform: ${props.sidebarOpen ? "scaleX(3)" : "scaleX(1)"};
     .
     .
     .
`

I helped from here:

See here: Adding transitions to styled components

Does it work In this case?

Arman Ebrahimi
  • 2,035
  • 2
  • 7
  • 20
-1

Add a transition property like: transition:all 200ms ease-in;

ouflak
  • 2,458
  • 10
  • 44
  • 49
gottedev
  • 1
  • 1