Each sf::Sprite that is drawn uses a "draw call". The draw call is most often the most significant time wasted when drawing multiple objects. If there are very many sprites, the number of draw calls is high and
can cause performance issues.
However, using a vertex array (or similar) allows you to draw multiple shapes at once with just one draw call, which
can severely improve performance. Those shapes can be textured and rectangular so multiple sprites can be mimicked.
As for primitives, if you want to draw rectangles, you simply use the triangles primitives and create two triangles to create each rectangle. It requires a slight duplication of vertices and would therefore be 6 vertices per quad/rectangle:
sf::VertexArray rectangles(sf::PrimitiveType::Triangles, 12u); // 2 rectangles = 12 vertices
std::size_t firstVertexOfRectangle;
sf::Vector2f topLeft;
sf::Vector2f bottomRight;
// first rectangle: 100,100 - 300,200 (200x100)
firstVertexOfRectangle = 0u;
topLeft = { 100.f, 100.f };
bottomRight = { 300.f, 200.f };
rectangles[firstVertexOfRectangle + 0u].position = topLeft;
rectangles[firstVertexOfRectangle + 1u].position = { topLeft.x, bottomRight.y };
rectangles[firstVertexOfRectangle + 2u].position = bottomRight;
rectangles[firstVertexOfRectangle + 5u].position = { topLeft.y, bottomRight.x };
rectangles[firstVertexOfRectangle + 3u] = rectangles[firstVertexOfRectangle + 0u];
rectangles[firstVertexOfRectangle + 4u] = rectangles[firstVertexOfRectangle + 2u];
// second rectangle: 500,200 - 600,500 (100x300)
firstVertexOfRectangle = 6u;
topLeft = { 500.f, 200.f };
bottomRight = { 600.f, 500.f };
rectangles[firstVertexOfRectangle + 0u].position = topLeft;
rectangles[firstVertexOfRectangle + 1u].position = { topLeft.x, bottomRight.y };
rectangles[firstVertexOfRectangle + 2u].position = bottomRight;
rectangles[firstVertexOfRectangle + 5u].position = { topLeft.y, bottomRight.x };
rectangles[firstVertexOfRectangle + 3u] = rectangles[firstVertexOfRectangle + 0u];
rectangles[firstVertexOfRectangle + 4u] = rectangles[firstVertexOfRectangle + 2u];
// later: window.draw(rectangles); // draws both rectangles with just one draw code
Note that the actual assigning of the vertices is the same both times.
You can assign colours and the texture co-ordinates in the same way. You can do that before the assigning of the "+ 3u" and "+ 4u" (at the time when the positions are assigned) as we're duplicating the entire vertex including colour and texture!