In version 0.8.12, Solidity introduced the concat() method to simplify string concatenation in smart contracts.

string.concat() accepts any number of arguments and returns a single string. Arguments must be strings or implicitly convertible to string. Otherwise, the value of the argument must be converted to a string first.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract StringConcat {
    string greeting = "Howdy, ";

    function greet(string memory _name) public view returns (string memory) {
        return string.concat(greeting, _name, '!');
    }

    // calling greet("Wayne") returns "Howdy, Wayne!"
}

In versions 0.8.11 and below, strings are concatenated with the abi.encodePacked() method.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

contract StringConcat {
    string greeting = "Howdy, ";

    function greet(string memory _name) public view returns (string memory) {
        return string(abi.encodePacked(greeting, _name, '!'));
    }

    // calling greet("Wayne") returns "Howdy, Wayne!"
}